1 #include "tools/ccanlint/ccanlint.h"
2 #include "ccan/tap/tap.h"
3 #include "tools/ccanlint/file_analysis.c"
10 /* This is our test file. */
12 enum line_info_type type;
17 static struct test testfile[] = {
18 { PREPROC_LINE, false, "#ifndef TEST_H" },
19 { PREPROC_LINE, false, "#define TEST_H" },
20 { DOC_LINE, false, "/**" },
21 { DOC_LINE, false, " * Comment here." },
22 { DOC_LINE, false, " * Comment here too." },
23 { DOC_LINE, false, " */" },
24 { COMMENT_LINE, false, "// Normal one-line comment" },
25 { COMMENT_LINE, false, " // Spaced one-line comment" },
26 { COMMENT_LINE, false, "/* Normal one-line comment */" },
27 { COMMENT_LINE, false, " /* Spaced one-line comment */" },
28 { COMMENT_LINE, false, " /* Spaced two-line comment" },
29 { COMMENT_LINE, false, " continued comment */" },
30 { CODE_LINE, false, "extern int x;"},
31 { CODE_LINE, false, "extern int y; // With new-style comment"},
32 { CODE_LINE, false, "extern int z; /* With old-style comment */"},
33 { CODE_LINE, false, "extern int v; /* With two-line comment"},
34 { COMMENT_LINE, false, " Second line of comment"},
35 { COMMENT_LINE, false, "/* comment1 */ // comment 2"},
36 { COMMENT_LINE, false, "/* comment1 */ /* comment 2 */ "},
37 { CODE_LINE, false, "/* comment1 */ code; /* comment 2 */ "},
38 { CODE_LINE, false, "/* comment1 */ code; // comment 2"},
39 { COMMENT_LINE, false, "/* comment start \\"},
40 { COMMENT_LINE, true, " comment finish */"},
41 { PREPROC_LINE, false, "#define foo \\"},
42 { PREPROC_LINE, true, " (bar + \\"},
43 { PREPROC_LINE, true, " baz)"},
44 { CODE_LINE, false, "extern int \\"},
45 { CODE_LINE, true, "#x;"},
47 /* Variants of the same thing. */
48 { PREPROC_LINE, false, "#ifdef BAR"},
49 { CODE_LINE, false, "BAR"},
50 { PREPROC_LINE, false, "#else"},
51 { CODE_LINE, false, "!BAR"},
52 { PREPROC_LINE, false, "#endif"},
54 { PREPROC_LINE, false, "#if defined BAR"},
55 { CODE_LINE, false, "BAR"},
56 { PREPROC_LINE, false, "#else"},
57 { CODE_LINE, false, "!BAR"},
58 { PREPROC_LINE, false, "#endif"},
60 { PREPROC_LINE, false, "#if defined(BAR)"},
61 { CODE_LINE, false, "BAR"},
62 { PREPROC_LINE, false, "#else"},
63 { CODE_LINE, false, "!BAR"},
64 { PREPROC_LINE, false, "#endif"},
66 { PREPROC_LINE, false, "#if !defined(BAR)"},
67 { CODE_LINE, false, "!BAR"},
68 { PREPROC_LINE, false, "#else"},
69 { CODE_LINE, false, "BAR"},
70 { PREPROC_LINE, false, "#endif"},
72 { PREPROC_LINE, false, "#if HAVE_FOO"},
73 { CODE_LINE, false, "HAVE_FOO"},
74 { PREPROC_LINE, false, "#elif HAVE_BAR"},
75 { CODE_LINE, false, "HAVE_BAR"},
76 { PREPROC_LINE, false, "#else"},
77 { CODE_LINE, false, "neither"},
78 { PREPROC_LINE, false, "#endif /* With a comment. */"},
80 { PREPROC_LINE, false, "#endif /* TEST_H */" },
83 #define NUM_LINES (sizeof(testfile)/sizeof(testfile[0]))
85 static const char *line_type_name(enum line_info_type type)
88 case PREPROC_LINE: return "PREPROC_LINE";
89 case CODE_LINE: return "CODE_LINE";
90 case DOC_LINE: return "DOC_LINE";
91 case COMMENT_LINE: return "COMMENT_LINE";
92 default: return "**INVALID**";
96 /* This just tests parser for the moment. */
97 int main(int argc, char *argv[])
100 struct line_info *line_info;
101 struct ccan_file *f = tal(NULL, struct ccan_file);
103 plan_tests(NUM_LINES * 2 + 2 + 86);
105 f->num_lines = NUM_LINES;
107 f->lines = tal_array(f, char *, f->num_lines);
108 for (i = 0; i < f->num_lines; i++)
109 f->lines[i] = tal_strdup(f->lines, testfile[i].line);
111 line_info = get_ccan_line_info(f);
112 ok1(line_info == f->line_info);
113 for (i = 0; i < f->num_lines; i++) {
114 ok(f->line_info[i].type == testfile[i].type,
115 "Line %u:'%s' type %s should be %s",
117 line_type_name(f->line_info[i].type),
118 line_type_name(testfile[i].type));
119 ok(f->line_info[i].continued == testfile[i].continued,
120 "Line %u:'%s' continued should be %s",
122 testfile[i].continued ? "TRUE" : "FALSE");
126 ok1(get_ccan_line_info(f) == line_info);
128 /* Expect line 1 condition to be NULL. */
129 ok1(line_info[0].cond == NULL);
130 /* Line 2, should depend on TEST_H being undefined. */
131 ok1(line_info[1].cond != NULL);
132 ok1(line_info[1].cond->type == PP_COND_IFDEF);
133 ok1(line_info[1].cond->inverse);
134 ok1(line_info[1].cond->parent == NULL);
135 ok1(streq(line_info[1].cond->symbol, "TEST_H"));
137 /* Every line BAR should depend on BAR being defined. */
138 for (i = 0; i < f->num_lines; i++) {
139 if (!streq(testfile[i].line, "BAR"))
141 ok1(line_info[i].cond->type == PP_COND_IFDEF);
142 ok1(!line_info[i].cond->inverse);
143 ok1(streq(line_info[i].cond->symbol, "BAR"));
144 ok1(line_info[i].cond->parent == line_info[1].cond);
147 /* Every line !BAR should depend on BAR being undefined. */
148 for (i = 0; i < f->num_lines; i++) {
149 if (!streq(testfile[i].line, "!BAR"))
151 ok1(line_info[i].cond->type == PP_COND_IFDEF);
152 ok1(line_info[i].cond->inverse);
153 ok1(streq(line_info[i].cond->symbol, "BAR"));
154 ok1(line_info[i].cond->parent == line_info[1].cond);
157 /* Every line HAVE_BAR should depend on HAVE_BAR being set. */
158 for (i = 0; i < f->num_lines; i++) {
159 if (!streq(testfile[i].line, "HAVE_BAR"))
161 ok1(line_info[i].cond->type == PP_COND_IF);
162 ok1(!line_info[i].cond->inverse);
163 ok1(streq(line_info[i].cond->symbol, "HAVE_BAR"));
164 ok1(line_info[i].cond->parent == line_info[1].cond);
167 /* Every line HAVE_FOO should depend on HAVE_FOO being set. */
168 for (i = 0; i < f->num_lines; i++) {
169 if (!streq(testfile[i].line, "HAVE_FOO"))
171 ok1(line_info[i].cond->type == PP_COND_IF);
172 ok1(!line_info[i].cond->inverse);
173 ok1(streq(line_info[i].cond->symbol, "HAVE_FOO"));
174 ok1(line_info[i].cond->parent == line_info[1].cond);
177 /* Now check using interface. */
178 for (i = 0; i < f->num_lines; i++) {
179 unsigned int val = 1;
180 if (streq(testfile[i].line, "BAR")) {
181 /* If we don't know if the TEST_H was undefined,
182 * best we get is a MAYBE. */
183 ok1(get_ccan_line_pp(line_info[i].cond, "BAR", &val,
184 NULL) == MAYBE_COMPILED);
185 ok1(get_ccan_line_pp(line_info[i].cond, "BAR", NULL,
186 NULL) == NOT_COMPILED);
187 ok1(get_ccan_line_pp(line_info[i].cond, "BAR", &val,
190 ok1(get_ccan_line_pp(line_info[i].cond, "BAR", NULL,
192 NULL) == NOT_COMPILED);
193 } else if (streq(testfile[i].line, "!BAR")) {
194 ok1(get_ccan_line_pp(line_info[i].cond, "BAR", &val,
195 NULL) == NOT_COMPILED);
196 ok1(get_ccan_line_pp(line_info[i].cond, "BAR", NULL,
197 NULL) == MAYBE_COMPILED);
198 ok1(get_ccan_line_pp(line_info[i].cond, "BAR", &val,
200 NULL) == NOT_COMPILED);
201 ok1(get_ccan_line_pp(line_info[i].cond, "BAR", NULL,
204 } else if (streq(testfile[i].line, "HAVE_BAR")) {
205 ok1(get_ccan_line_pp(line_info[i].cond, "HAVE_BAR",
206 &val, NULL) == MAYBE_COMPILED);
207 ok1(get_ccan_line_pp(line_info[i].cond, "HAVE_BAR",
208 &val, "TEST_H", NULL,
211 ok1(get_ccan_line_pp(line_info[i].cond, "HAVE_BAR",
212 &val, NULL) == NOT_COMPILED);
213 ok1(get_ccan_line_pp(line_info[i].cond, "HAVE_BAR",
214 &val, "TEST_H", NULL,
215 NULL) == NOT_COMPILED);
216 } else if (streq(testfile[i].line, "HAVE_FOO")) {
217 ok1(get_ccan_line_pp(line_info[i].cond, "HAVE_FOO",
218 &val, NULL) == MAYBE_COMPILED);
219 ok1(get_ccan_line_pp(line_info[i].cond, "HAVE_FOO",
220 &val, "TEST_H", NULL,
223 ok1(get_ccan_line_pp(line_info[i].cond, "HAVE_FOO",
224 &val, NULL) == NOT_COMPILED);
225 ok1(get_ccan_line_pp(line_info[i].cond, "HAVE_FOO",
226 &val, "TEST_H", NULL,
227 NULL) == NOT_COMPILED);
231 return exit_status();