blob: 9345536c0cc3fc1c2cd8f5fdaab2f03174b1632d [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
Lev Walkin93659562010-11-20 09:47:13 -08004#ifdef _WIN32
Lev Walkin4efbfb72005-02-25 14:20:30 +00005#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
Lev Walkine0d321a2014-09-11 01:28:57 -070016#ifndef TOP_SRCDIR
17#define TOP_SRCDIR_S ".."
18#else
19#define STRINGIFY_MACRO2(x) #x
20#define STRINGIFY_MACRO(x) STRINGIFY_MACRO2(x)
21#define TOP_SRCDIR_S STRINGIFY_MACRO(TOP_SRCDIR)
22#endif
23
Lev Walkin55982b82016-03-14 03:56:16 -070024static int check(const char *fname,
Lev Walkinf15320b2004-06-03 03:38:44 +000025 enum asn1p_flags parser_flags,
26 enum asn1f_flags fixer_flags);
27static int post_fix_check(asn1p_t *asn);
28static int post_fix_check_element(asn1p_module_t *mod, asn1p_expr_t *expr);
29
30int
31main(int ac, char **av) {
Lev Walkin93659562010-11-20 09:47:13 -080032#ifdef _WIN32
Lev Walkin4efbfb72005-02-25 14:20:30 +000033 intptr_t dir;
34 struct _finddata_t c_file;
35#else
Lev Walkinf15320b2004-06-03 03:38:44 +000036 struct dirent *dp;
37 DIR *dir;
Lev Walkin4efbfb72005-02-25 14:20:30 +000038#endif
Lev Walkinf15320b2004-06-03 03:38:44 +000039 int failed = 0;
40 int completed = 0;
41 enum asn1p_flags parser_flags = A1P_NOFLAGS;
42 enum asn1f_flags fixer_flags = A1F_NOFLAGS;
Lev Walkin4efbfb72005-02-25 14:20:30 +000043 const char *filename;
Lev Walkin07721d52005-02-25 14:35:02 +000044 size_t len;
Lev Walkinf15320b2004-06-03 03:38:44 +000045 int ret;
46
47 /*
48 * Just in case when one decides that some flags better be
49 * enabled during `ASN1_FIXER_FLAGS=1 make check` or some
50 * similar usage.
51 */
52 if(getenv("ASN1_PARSER_FLAGS"))
53 parser_flags = atoi(getenv("ASN1_PARSER_FLAGS"));
54 if(getenv("ASN1_FIXER_FLAGS"))
55 fixer_flags = atoi(getenv("ASN1_FIXER_FLAGS"));
56
57 /*
58 * Go into a directory with tests.
59 */
60 if(ac <= 1) {
Lev Walkin08068b22016-01-24 22:49:06 -080061 const char *asn1_tests_dir = getenv("ASN1_TESTS_DIR");
62 if(!asn1_tests_dir)
63 asn1_tests_dir = TOP_SRCDIR_S "/tests";
64 fprintf(stderr, "Testing in %s...\n", asn1_tests_dir);
65 ret = chdir(asn1_tests_dir);
66 if(ret == -1)
67 fprintf(stderr, "%s: %s\n", asn1_tests_dir, strerror(errno));
68 assert(ret == 0);
Lev Walkin9e66d162016-03-14 03:36:35 -070069 /* For some reasons, tests could be hidden under extra tests dir. */
Lev Walkin93659562010-11-20 09:47:13 -080070#ifdef _WIN32
Lev Walkin4efbfb72005-02-25 14:20:30 +000071 dir = _findfirst("*.asn1", &c_file);
72 assert(dir != -1L);
73#else
Lev Walkinf15320b2004-06-03 03:38:44 +000074 dir = opendir(".");
75 assert(dir);
Lev Walkin93659562010-11-20 09:47:13 -080076#endif /* _WIN32 */
Lev Walkinf15320b2004-06-03 03:38:44 +000077 } else {
78 dir = 0;
79 }
80
81 /*
82 * Scan every *.asn1 file and try to parse and fix it.
83 */
84 if(dir) {
Lev Walkin93659562010-11-20 09:47:13 -080085#ifdef _WIN32
Lev Walkin4efbfb72005-02-25 14:20:30 +000086 do {
87 filename = c_file.name;
88#else
Lev Walkinf15320b2004-06-03 03:38:44 +000089 while((dp = readdir(dir))) {
Lev Walkin4efbfb72005-02-25 14:20:30 +000090 filename = dp->d_name;
Lev Walkin93659562010-11-20 09:47:13 -080091#endif /* _WIN32 */
Lev Walkin07721d52005-02-25 14:35:02 +000092 len = strlen(filename);
Lev Walkin4b553412005-08-14 14:45:44 +000093 if(len <= 5 || strcmp(filename + len - 5, ".asn1"))
94 continue;
Lev Walkin55982b82016-03-14 03:56:16 -070095 ret = check(filename, parser_flags, fixer_flags);
Lev Walkin4b553412005-08-14 14:45:44 +000096 if(ret) {
97 fprintf(stderr, "FAILED: %s\n",
98 filename);
99 failed++;
Lev Walkinf15320b2004-06-03 03:38:44 +0000100 }
Lev Walkin4b553412005-08-14 14:45:44 +0000101 completed++;
Lev Walkin93659562010-11-20 09:47:13 -0800102#ifdef _WIN32
Lev Walkin4efbfb72005-02-25 14:20:30 +0000103 } while(_findnext(dir, &c_file) == 0);
104 _findclose(dir);
105#else
Lev Walkinf15320b2004-06-03 03:38:44 +0000106 }
107 closedir(dir);
Lev Walkin93659562010-11-20 09:47:13 -0800108#endif /* _WIN32 */
Lev Walkin4efbfb72005-02-25 14:20:30 +0000109
Lev Walkinf15320b2004-06-03 03:38:44 +0000110
111 fprintf(stderr,
112 "Tests COMPLETED: %d\n"
113 "Tests FAILED: %d\n"
114 ,
115 completed, failed
116 );
117 } else {
118 int i;
119 for(i = 1; i < ac; i++) {
Lev Walkin55982b82016-03-14 03:56:16 -0700120 ret = check(av[i], parser_flags, fixer_flags);
Lev Walkinf15320b2004-06-03 03:38:44 +0000121 if(ret) {
122 fprintf(stderr, "FAILED: %s\n", av[i]);
123 failed++;
124 }
125 completed++;
126 }
127 }
128
129 if(completed == 0) {
130 fprintf(stderr, "No tests defined?!\n");
131 exit(EX_NOINPUT);
132 }
133
134 if(failed)
135 exit(EX_DATAERR);
136 return 0;
137}
138
139static int
Lev Walkin55982b82016-03-14 03:56:16 -0700140check(const char *fname,
Lev Walkinf15320b2004-06-03 03:38:44 +0000141 enum asn1p_flags parser_flags,
142 enum asn1f_flags fixer_flags) {
143 asn1p_t *asn;
144 int expected_parseable; /* Is it expected to be parseable? */
145 int expected_fix_code; /* What code a fixer must return */
146 int r_value = 0;
147
148 /*
149 * Figure out how the processing should go by inferring
150 * expectations from the file name.
151 */
152 if(strstr(fname, "-OK.")) {
153 expected_parseable = 1;
154 expected_fix_code = 0;
155 } else if(strstr(fname, "-NP.")) {
156 expected_parseable = 0;
157 expected_fix_code = 123; /* Does not matter */
158 } else if(strstr(fname, "-SE.")) {
159 expected_parseable = 1;
160 expected_fix_code = -1; /* Semantically incorrect */
161 } else if(strstr(fname, "-SW.")) {
162 expected_parseable = 1;
163 expected_fix_code = 1; /* Semantically suspicious */
164 } else {
165 fprintf(stderr, "%s: Invalid file name format\n", fname);
166 return -1;
167 }
168
Lev Walkin4b553412005-08-14 14:45:44 +0000169 /* Flag modifiers */
170 if(strstr(fname, "-blessSize-"))
171 fixer_flags |= A1F_EXTENDED_SizeConstraint;
172
Lev Walkinf15320b2004-06-03 03:38:44 +0000173 fprintf(stderr, "[=> %s]\n", fname);
174
175 /*
176 * Perform low-level parsing.
177 */
178 if(!expected_parseable)
179 fprintf(stderr, "Expecting error...\n");
180 asn = asn1p_parse_file(fname, parser_flags);
181 if(asn == NULL) {
182 if(expected_parseable) {
183 fprintf(stderr, "Cannot parse file \"%s\"\n", fname);
184 r_value = -1;
185 } else {
186 fprintf(stderr,
187 "Previous error is EXPECTED, no worry\n");
188 }
189 } else if(!expected_parseable) {
190 fprintf(stderr,
191 "The file \"%s\" is not expected to be parseable, "
192 "yet parsing was successfull!\n", fname);
193 r_value = -1;
194 }
Lev Walkin6b3ff542006-03-06 14:51:00 +0000195 if(!asn) return r_value;
196
197 if(r_value == 0) {
198 asn1p_t *std_asn;
Lev Walkin55982b82016-03-14 03:56:16 -0700199 std_asn = asn1p_parse_file("../skeletons/standard-modules/ASN1C-UsefulInformationObjectClasses.asn1", A1P_NOFLAGS);
Lev Walkin6b3ff542006-03-06 14:51:00 +0000200 if(std_asn) {
201 asn1p_module_t *mod;
Lev Walkin9c2285a2006-03-09 08:49:26 +0000202 while((mod = TQ_REMOVE(&(std_asn->modules), mod_next))) {
203 mod->_tags |= MT_STANDARD_MODULE;
Lev Walkin6b3ff542006-03-06 14:51:00 +0000204 TQ_ADD(&(asn->modules), mod, mod_next);
Lev Walkin9c2285a2006-03-09 08:49:26 +0000205 }
Lev Walkin223000a2006-09-13 00:21:58 +0000206 asn1p_delete(std_asn);
Lev Walkin6b3ff542006-03-06 14:51:00 +0000207 }
208 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000209
210 /*
211 * Perform semantical checks and fixes.
212 */
Lev Walkin6b3ff542006-03-06 14:51:00 +0000213 if(r_value == 0) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000214 int ret;
215
216 if(expected_fix_code)
217 fprintf(stderr, "Expecting some problems...\n");
218
219 ret = asn1f_process(asn, fixer_flags, 0);
220 if(ret) {
221 if(ret == expected_fix_code) {
222 fprintf(stderr,
223 "Previous error is EXPECTED, "
224 "no worry\n");
225 } else {
226 fprintf(stderr,
227 "Cannot process file \"%s\": %d\n",
228 fname, ret);
229 r_value = -1;
230 }
231 } else if(ret != expected_fix_code) {
232 fprintf(stderr,
233 "File \"%s\" is expected "
234 "to be semantically incorrect, "
235 "yet processing was successful!\n",
236 fname);
237 r_value = -1;
238 }
239 }
240
241 /*
242 * Check validity of some values, if grammar has special
243 * instructions for that.
244 */
Lev Walkin6b3ff542006-03-06 14:51:00 +0000245 if(r_value == 0) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000246 if(post_fix_check(asn))
247 r_value = -1;
248 }
249
250 /*
Lev Walkin6b3ff542006-03-06 14:51:00 +0000251 * Destroy the asn.
Lev Walkinf15320b2004-06-03 03:38:44 +0000252 */
Lev Walkin55f106a2006-09-15 16:34:12 +0000253#ifdef CLEAN_EVERYTHING
Lev Walkin223000a2006-09-13 00:21:58 +0000254 asn1p_delete(asn);
Lev Walkin55f106a2006-09-15 16:34:12 +0000255#endif
Lev Walkinf15320b2004-06-03 03:38:44 +0000256
257 return r_value;
258}
259
260
261static int
262post_fix_check(asn1p_t *asn) {
263 asn1p_module_t *mod;
264 asn1p_expr_t *expr;
265 int r_value = 0;
266
267 TQ_FOR(mod, &(asn->modules), mod_next) {
268 TQ_FOR(expr, &(mod->members), next) {
269 assert(expr->Identifier);
270 if(strncmp(expr->Identifier, "check-", 6) == 0) {
271 if(post_fix_check_element(mod, expr))
272 r_value = -1;
273 }
274 }
275 }
276
277 return r_value;
278}
279
280
281static int
282post_fix_check_element(asn1p_module_t *mod, asn1p_expr_t *check_expr) {
283 asn1p_expr_t *expr = NULL;
284 char *name;
285 asn1p_value_t *value;
286
287 if(check_expr->expr_type != ASN_BASIC_INTEGER
288 || check_expr->meta_type != AMT_VALUE) {
289 fprintf(stderr,
290 "CHECKER: Unsupported type of \"%s\" value: "
291 "%d at line %d of %s\n",
292 check_expr->Identifier,
293 check_expr->expr_type,
294 check_expr->_lineno,
295 mod->source_file_name
296 );
297 return -1;
298 }
299
300 assert(check_expr->meta_type == AMT_VALUE);
301
302 value = check_expr->value;
303 if(value == NULL || value->type != ATV_INTEGER) {
304 fprintf(stderr,
305 "CHECKER: Unsupported value type of \"%s\": "
306 "%d at line %d of %s\n",
307 check_expr->Identifier,
Lev Walkin409c44e2004-06-05 08:57:10 +0000308 value?(signed)value->type:-1,
Lev Walkinf15320b2004-06-03 03:38:44 +0000309 expr->_lineno,
310 mod->source_file_name
311 );
312 return -1;
313 }
314
315 name = check_expr->Identifier + sizeof("check-") - 1;
316
317 /*
318 * Scan in search for the original.
319 */
320 TQ_FOR(expr, &(mod->members), next) {
321 if(strcmp(expr->Identifier, name) == 0)
322 break;
323 }
324
325 if(expr == NULL) {
326 fprintf(stderr,
327 "CHECKER: Value \"%s\" requested by "
328 "\"check-%s\" at line %d of %s is not found!\n",
329 name, name, check_expr->_lineno,
330 mod->source_file_name
331 );
332 return -1;
333 }
334
335 if(0 && expr->expr_type != check_expr->expr_type) {
336 fprintf(stderr,
337 "CHECKER: Value type of \"%s\" (=%d) at line %d "
338 "does not have desired type %d as requested by "
339 "\"check-%s\" in %s\n",
340 expr->Identifier,
341 expr->expr_type,
342 expr->_lineno,
343 check_expr->expr_type,
344 name,
345 mod->source_file_name
346 );
347 return -1;
348 }
349
350 if(expr->value == NULL
351 || expr->value->type != value->type) {
352 fprintf(stderr,
353 "CHECKER: Value of \"%s\" (\"%s\", type=%d) at line %d "
354 "does not have desired type %d as requested by "
355 "\"check-%s\" in %s\n",
356 expr->Identifier,
357 asn1f_printable_value(expr->value),
358 expr->value->type,
359 expr->_lineno,
360 value->type,
361 name,
362 mod->source_file_name
363 );
364 return -1;
365 }
366
367 assert(value->type = ATV_INTEGER);
368
369 return 0;
370}
371
372