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