blob: 7129a5631061b4e59a5c39c7de9577901be3180b [file] [log] [blame]
Lev Walkinf15320b2004-06-03 03:38:44 +00001#undef NDEBUG
2#include <stdio.h>
3#include <stdlib.h>
4#include <string.h>
5#include <sys/types.h>
6#include <unistd.h>
7#include <dirent.h>
8#include <errno.h>
9#include <sysexits.h>
10
11#include "asn1fix.h"
12#include "asn1fix_internal.h"
13
14static int check(const char *fname,
15 enum asn1p_flags parser_flags,
16 enum asn1f_flags fixer_flags);
17static int post_fix_check(asn1p_t *asn);
18static int post_fix_check_element(asn1p_module_t *mod, asn1p_expr_t *expr);
19
20int
21main(int ac, char **av) {
22 struct dirent *dp;
23 DIR *dir;
24 int failed = 0;
25 int completed = 0;
26 enum asn1p_flags parser_flags = A1P_NOFLAGS;
27 enum asn1f_flags fixer_flags = A1F_NOFLAGS;
28 int ret;
29
30 /*
31 * Just in case when one decides that some flags better be
32 * enabled during `ASN1_FIXER_FLAGS=1 make check` or some
33 * similar usage.
34 */
35 if(getenv("ASN1_PARSER_FLAGS"))
36 parser_flags = atoi(getenv("ASN1_PARSER_FLAGS"));
37 if(getenv("ASN1_FIXER_FLAGS"))
38 fixer_flags = atoi(getenv("ASN1_FIXER_FLAGS"));
39
40 /*
41 * Go into a directory with tests.
42 */
43 if(ac <= 1) {
44 fprintf(stderr, "Testing in ./tests...\n");
45 ret = chdir("../tests");
46 assert(ret == 0);
47 dir = opendir(".");
48 assert(dir);
49 } else {
50 dir = 0;
51 }
52
53 /*
54 * Scan every *.asn1 file and try to parse and fix it.
55 */
56 if(dir) {
57 while((dp = readdir(dir))) {
58 int len = strlen(dp->d_name);
59 if(len && strcmp(dp->d_name + len - 5, ".asn1") == 0) {
60 ret = check(dp->d_name,
61 parser_flags, fixer_flags);
62 if(ret) {
63 fprintf(stderr,
64 "FAILED: %s\n",
65 dp->d_name);
66 failed++;
67 }
68 completed++;
69 }
70 }
71 closedir(dir);
72
73 fprintf(stderr,
74 "Tests COMPLETED: %d\n"
75 "Tests FAILED: %d\n"
76 ,
77 completed, failed
78 );
79 } else {
80 int i;
81 for(i = 1; i < ac; i++) {
82 ret = check(av[i], parser_flags, fixer_flags);
83 if(ret) {
84 fprintf(stderr, "FAILED: %s\n", av[i]);
85 failed++;
86 }
87 completed++;
88 }
89 }
90
91 if(completed == 0) {
92 fprintf(stderr, "No tests defined?!\n");
93 exit(EX_NOINPUT);
94 }
95
96 if(failed)
97 exit(EX_DATAERR);
98 return 0;
99}
100
101static int
102check(const char *fname,
103 enum asn1p_flags parser_flags,
104 enum asn1f_flags fixer_flags) {
105 asn1p_t *asn;
106 int expected_parseable; /* Is it expected to be parseable? */
107 int expected_fix_code; /* What code a fixer must return */
108 int r_value = 0;
109
110 /*
111 * Figure out how the processing should go by inferring
112 * expectations from the file name.
113 */
114 if(strstr(fname, "-OK.")) {
115 expected_parseable = 1;
116 expected_fix_code = 0;
117 } else if(strstr(fname, "-NP.")) {
118 expected_parseable = 0;
119 expected_fix_code = 123; /* Does not matter */
120 } else if(strstr(fname, "-SE.")) {
121 expected_parseable = 1;
122 expected_fix_code = -1; /* Semantically incorrect */
123 } else if(strstr(fname, "-SW.")) {
124 expected_parseable = 1;
125 expected_fix_code = 1; /* Semantically suspicious */
126 } else {
127 fprintf(stderr, "%s: Invalid file name format\n", fname);
128 return -1;
129 }
130
131 fprintf(stderr, "[=> %s]\n", fname);
132
133 /*
134 * Perform low-level parsing.
135 */
136 if(!expected_parseable)
137 fprintf(stderr, "Expecting error...\n");
138 asn = asn1p_parse_file(fname, parser_flags);
139 if(asn == NULL) {
140 if(expected_parseable) {
141 fprintf(stderr, "Cannot parse file \"%s\"\n", fname);
142 r_value = -1;
143 } else {
144 fprintf(stderr,
145 "Previous error is EXPECTED, no worry\n");
146 }
147 } else if(!expected_parseable) {
148 fprintf(stderr,
149 "The file \"%s\" is not expected to be parseable, "
150 "yet parsing was successfull!\n", fname);
151 r_value = -1;
152 }
153
154 /*
155 * Perform semantical checks and fixes.
156 */
157 if(asn && r_value == 0) {
158 int ret;
159
160 if(expected_fix_code)
161 fprintf(stderr, "Expecting some problems...\n");
162
163 ret = asn1f_process(asn, fixer_flags, 0);
164 if(ret) {
165 if(ret == expected_fix_code) {
166 fprintf(stderr,
167 "Previous error is EXPECTED, "
168 "no worry\n");
169 } else {
170 fprintf(stderr,
171 "Cannot process file \"%s\": %d\n",
172 fname, ret);
173 r_value = -1;
174 }
175 } else if(ret != expected_fix_code) {
176 fprintf(stderr,
177 "File \"%s\" is expected "
178 "to be semantically incorrect, "
179 "yet processing was successful!\n",
180 fname);
181 r_value = -1;
182 }
183 }
184
185 /*
186 * Check validity of some values, if grammar has special
187 * instructions for that.
188 */
189 if(asn && r_value == 0) {
190 if(post_fix_check(asn))
191 r_value = -1;
192 }
193
194 /*
195 * TODO: destroy the asn.
196 */
197
198 return r_value;
199}
200
201
202static int
203post_fix_check(asn1p_t *asn) {
204 asn1p_module_t *mod;
205 asn1p_expr_t *expr;
206 int r_value = 0;
207
208 TQ_FOR(mod, &(asn->modules), mod_next) {
209 TQ_FOR(expr, &(mod->members), next) {
210 assert(expr->Identifier);
211 if(strncmp(expr->Identifier, "check-", 6) == 0) {
212 if(post_fix_check_element(mod, expr))
213 r_value = -1;
214 }
215 }
216 }
217
218 return r_value;
219}
220
221
222static int
223post_fix_check_element(asn1p_module_t *mod, asn1p_expr_t *check_expr) {
224 asn1p_expr_t *expr = NULL;
225 char *name;
226 asn1p_value_t *value;
227
228 if(check_expr->expr_type != ASN_BASIC_INTEGER
229 || check_expr->meta_type != AMT_VALUE) {
230 fprintf(stderr,
231 "CHECKER: Unsupported type of \"%s\" value: "
232 "%d at line %d of %s\n",
233 check_expr->Identifier,
234 check_expr->expr_type,
235 check_expr->_lineno,
236 mod->source_file_name
237 );
238 return -1;
239 }
240
241 assert(check_expr->meta_type == AMT_VALUE);
242
243 value = check_expr->value;
244 if(value == NULL || value->type != ATV_INTEGER) {
245 fprintf(stderr,
246 "CHECKER: Unsupported value type of \"%s\": "
247 "%d at line %d of %s\n",
248 check_expr->Identifier,
Lev Walkin409c44e2004-06-05 08:57:10 +0000249 value?(signed)value->type:-1,
Lev Walkinf15320b2004-06-03 03:38:44 +0000250 expr->_lineno,
251 mod->source_file_name
252 );
253 return -1;
254 }
255
256 name = check_expr->Identifier + sizeof("check-") - 1;
257
258 /*
259 * Scan in search for the original.
260 */
261 TQ_FOR(expr, &(mod->members), next) {
262 if(strcmp(expr->Identifier, name) == 0)
263 break;
264 }
265
266 if(expr == NULL) {
267 fprintf(stderr,
268 "CHECKER: Value \"%s\" requested by "
269 "\"check-%s\" at line %d of %s is not found!\n",
270 name, name, check_expr->_lineno,
271 mod->source_file_name
272 );
273 return -1;
274 }
275
276 if(0 && expr->expr_type != check_expr->expr_type) {
277 fprintf(stderr,
278 "CHECKER: Value type of \"%s\" (=%d) at line %d "
279 "does not have desired type %d as requested by "
280 "\"check-%s\" in %s\n",
281 expr->Identifier,
282 expr->expr_type,
283 expr->_lineno,
284 check_expr->expr_type,
285 name,
286 mod->source_file_name
287 );
288 return -1;
289 }
290
291 if(expr->value == NULL
292 || expr->value->type != value->type) {
293 fprintf(stderr,
294 "CHECKER: Value of \"%s\" (\"%s\", type=%d) at line %d "
295 "does not have desired type %d as requested by "
296 "\"check-%s\" in %s\n",
297 expr->Identifier,
298 asn1f_printable_value(expr->value),
299 expr->value->type,
300 expr->_lineno,
301 value->type,
302 name,
303 mod->source_file_name
304 );
305 return -1;
306 }
307
308 assert(value->type = ATV_INTEGER);
309
310 return 0;
311}
312
313