blob: 18633241560abaf8f35782ca2115e2c0ed6b08a2 [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 Walkin9e66d162016-03-14 03:36:35 -070024static int check(int skeletons_hier_level, 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 Walkin9e66d162016-03-14 03:36:35 -070044 int skeletons_hier_level = 1;
Lev Walkin07721d52005-02-25 14:35:02 +000045 size_t len;
Lev Walkinf15320b2004-06-03 03:38:44 +000046 int ret;
47
48 /*
49 * Just in case when one decides that some flags better be
50 * enabled during `ASN1_FIXER_FLAGS=1 make check` or some
51 * similar usage.
52 */
53 if(getenv("ASN1_PARSER_FLAGS"))
54 parser_flags = atoi(getenv("ASN1_PARSER_FLAGS"));
55 if(getenv("ASN1_FIXER_FLAGS"))
56 fixer_flags = atoi(getenv("ASN1_FIXER_FLAGS"));
57
58 /*
59 * Go into a directory with tests.
60 */
61 if(ac <= 1) {
Lev Walkin08068b22016-01-24 22:49:06 -080062 const char *asn1_tests_dir = getenv("ASN1_TESTS_DIR");
63 if(!asn1_tests_dir)
64 asn1_tests_dir = TOP_SRCDIR_S "/tests";
65 fprintf(stderr, "Testing in %s...\n", asn1_tests_dir);
66 ret = chdir(asn1_tests_dir);
67 if(ret == -1)
68 fprintf(stderr, "%s: %s\n", asn1_tests_dir, strerror(errno));
69 assert(ret == 0);
Lev Walkin9e66d162016-03-14 03:36:35 -070070 /* For some reasons, tests could be hidden under extra tests dir. */
71 if(chdir("tests") == 0) {
72 skeletons_hier_level++;
73 }
Lev Walkin93659562010-11-20 09:47:13 -080074#ifdef _WIN32
Lev Walkin4efbfb72005-02-25 14:20:30 +000075 dir = _findfirst("*.asn1", &c_file);
76 assert(dir != -1L);
77#else
Lev Walkinf15320b2004-06-03 03:38:44 +000078 dir = opendir(".");
79 assert(dir);
Lev Walkin93659562010-11-20 09:47:13 -080080#endif /* _WIN32 */
Lev Walkinf15320b2004-06-03 03:38:44 +000081 } else {
82 dir = 0;
83 }
84
85 /*
86 * Scan every *.asn1 file and try to parse and fix it.
87 */
88 if(dir) {
Lev Walkin93659562010-11-20 09:47:13 -080089#ifdef _WIN32
Lev Walkin4efbfb72005-02-25 14:20:30 +000090 do {
91 filename = c_file.name;
92#else
Lev Walkinf15320b2004-06-03 03:38:44 +000093 while((dp = readdir(dir))) {
Lev Walkin4efbfb72005-02-25 14:20:30 +000094 filename = dp->d_name;
Lev Walkin93659562010-11-20 09:47:13 -080095#endif /* _WIN32 */
Lev Walkin07721d52005-02-25 14:35:02 +000096 len = strlen(filename);
Lev Walkin4b553412005-08-14 14:45:44 +000097 if(len <= 5 || strcmp(filename + len - 5, ".asn1"))
98 continue;
Lev Walkin9e66d162016-03-14 03:36:35 -070099 ret = check(skeletons_hier_level, filename, parser_flags, fixer_flags);
Lev Walkin4b553412005-08-14 14:45:44 +0000100 if(ret) {
101 fprintf(stderr, "FAILED: %s\n",
102 filename);
103 failed++;
Lev Walkinf15320b2004-06-03 03:38:44 +0000104 }
Lev Walkin4b553412005-08-14 14:45:44 +0000105 completed++;
Lev Walkin93659562010-11-20 09:47:13 -0800106#ifdef _WIN32
Lev Walkin4efbfb72005-02-25 14:20:30 +0000107 } while(_findnext(dir, &c_file) == 0);
108 _findclose(dir);
109#else
Lev Walkinf15320b2004-06-03 03:38:44 +0000110 }
111 closedir(dir);
Lev Walkin93659562010-11-20 09:47:13 -0800112#endif /* _WIN32 */
Lev Walkin4efbfb72005-02-25 14:20:30 +0000113
Lev Walkinf15320b2004-06-03 03:38:44 +0000114
115 fprintf(stderr,
116 "Tests COMPLETED: %d\n"
117 "Tests FAILED: %d\n"
118 ,
119 completed, failed
120 );
121 } else {
122 int i;
123 for(i = 1; i < ac; i++) {
Lev Walkin9e66d162016-03-14 03:36:35 -0700124 ret = check(skeletons_hier_level, av[i], parser_flags, fixer_flags);
Lev Walkinf15320b2004-06-03 03:38:44 +0000125 if(ret) {
126 fprintf(stderr, "FAILED: %s\n", av[i]);
127 failed++;
128 }
129 completed++;
130 }
131 }
132
133 if(completed == 0) {
134 fprintf(stderr, "No tests defined?!\n");
135 exit(EX_NOINPUT);
136 }
137
138 if(failed)
139 exit(EX_DATAERR);
140 return 0;
141}
142
143static int
Lev Walkin9e66d162016-03-14 03:36:35 -0700144check(int skeletons_hier_level, const char *fname,
Lev Walkinf15320b2004-06-03 03:38:44 +0000145 enum asn1p_flags parser_flags,
146 enum asn1f_flags fixer_flags) {
147 asn1p_t *asn;
148 int expected_parseable; /* Is it expected to be parseable? */
149 int expected_fix_code; /* What code a fixer must return */
150 int r_value = 0;
151
152 /*
153 * Figure out how the processing should go by inferring
154 * expectations from the file name.
155 */
156 if(strstr(fname, "-OK.")) {
157 expected_parseable = 1;
158 expected_fix_code = 0;
159 } else if(strstr(fname, "-NP.")) {
160 expected_parseable = 0;
161 expected_fix_code = 123; /* Does not matter */
162 } else if(strstr(fname, "-SE.")) {
163 expected_parseable = 1;
164 expected_fix_code = -1; /* Semantically incorrect */
165 } else if(strstr(fname, "-SW.")) {
166 expected_parseable = 1;
167 expected_fix_code = 1; /* Semantically suspicious */
168 } else {
169 fprintf(stderr, "%s: Invalid file name format\n", fname);
170 return -1;
171 }
172
Lev Walkin4b553412005-08-14 14:45:44 +0000173 /* Flag modifiers */
174 if(strstr(fname, "-blessSize-"))
175 fixer_flags |= A1F_EXTENDED_SizeConstraint;
176
Lev Walkinf15320b2004-06-03 03:38:44 +0000177 fprintf(stderr, "[=> %s]\n", fname);
178
179 /*
180 * Perform low-level parsing.
181 */
182 if(!expected_parseable)
183 fprintf(stderr, "Expecting error...\n");
184 asn = asn1p_parse_file(fname, parser_flags);
185 if(asn == NULL) {
186 if(expected_parseable) {
187 fprintf(stderr, "Cannot parse file \"%s\"\n", fname);
188 r_value = -1;
189 } else {
190 fprintf(stderr,
191 "Previous error is EXPECTED, no worry\n");
192 }
193 } else if(!expected_parseable) {
194 fprintf(stderr,
195 "The file \"%s\" is not expected to be parseable, "
196 "yet parsing was successfull!\n", fname);
197 r_value = -1;
198 }
Lev Walkin6b3ff542006-03-06 14:51:00 +0000199 if(!asn) return r_value;
200
201 if(r_value == 0) {
202 asn1p_t *std_asn;
Lev Walkin9e66d162016-03-14 03:36:35 -0700203 std_asn = asn1p_parse_file(skeletons_hier_level == 1
204 ? "../skeletons/standard-modules/ASN1C-UsefulInformationObjectClasses.asn1"
205 : "../../skeletons/standard-modules/ASN1C-UsefulInformationObjectClasses.asn1"
206 , A1P_NOFLAGS);
Lev Walkin6b3ff542006-03-06 14:51:00 +0000207 if(std_asn) {
208 asn1p_module_t *mod;
Lev Walkin9c2285a2006-03-09 08:49:26 +0000209 while((mod = TQ_REMOVE(&(std_asn->modules), mod_next))) {
210 mod->_tags |= MT_STANDARD_MODULE;
Lev Walkin6b3ff542006-03-06 14:51:00 +0000211 TQ_ADD(&(asn->modules), mod, mod_next);
Lev Walkin9c2285a2006-03-09 08:49:26 +0000212 }
Lev Walkin223000a2006-09-13 00:21:58 +0000213 asn1p_delete(std_asn);
Lev Walkin6b3ff542006-03-06 14:51:00 +0000214 }
215 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000216
217 /*
218 * Perform semantical checks and fixes.
219 */
Lev Walkin6b3ff542006-03-06 14:51:00 +0000220 if(r_value == 0) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000221 int ret;
222
223 if(expected_fix_code)
224 fprintf(stderr, "Expecting some problems...\n");
225
226 ret = asn1f_process(asn, fixer_flags, 0);
227 if(ret) {
228 if(ret == expected_fix_code) {
229 fprintf(stderr,
230 "Previous error is EXPECTED, "
231 "no worry\n");
232 } else {
233 fprintf(stderr,
234 "Cannot process file \"%s\": %d\n",
235 fname, ret);
236 r_value = -1;
237 }
238 } else if(ret != expected_fix_code) {
239 fprintf(stderr,
240 "File \"%s\" is expected "
241 "to be semantically incorrect, "
242 "yet processing was successful!\n",
243 fname);
244 r_value = -1;
245 }
246 }
247
248 /*
249 * Check validity of some values, if grammar has special
250 * instructions for that.
251 */
Lev Walkin6b3ff542006-03-06 14:51:00 +0000252 if(r_value == 0) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000253 if(post_fix_check(asn))
254 r_value = -1;
255 }
256
257 /*
Lev Walkin6b3ff542006-03-06 14:51:00 +0000258 * Destroy the asn.
Lev Walkinf15320b2004-06-03 03:38:44 +0000259 */
Lev Walkin55f106a2006-09-15 16:34:12 +0000260#ifdef CLEAN_EVERYTHING
Lev Walkin223000a2006-09-13 00:21:58 +0000261 asn1p_delete(asn);
Lev Walkin55f106a2006-09-15 16:34:12 +0000262#endif
Lev Walkinf15320b2004-06-03 03:38:44 +0000263
264 return r_value;
265}
266
267
268static int
269post_fix_check(asn1p_t *asn) {
270 asn1p_module_t *mod;
271 asn1p_expr_t *expr;
272 int r_value = 0;
273
274 TQ_FOR(mod, &(asn->modules), mod_next) {
275 TQ_FOR(expr, &(mod->members), next) {
276 assert(expr->Identifier);
277 if(strncmp(expr->Identifier, "check-", 6) == 0) {
278 if(post_fix_check_element(mod, expr))
279 r_value = -1;
280 }
281 }
282 }
283
284 return r_value;
285}
286
287
288static int
289post_fix_check_element(asn1p_module_t *mod, asn1p_expr_t *check_expr) {
290 asn1p_expr_t *expr = NULL;
291 char *name;
292 asn1p_value_t *value;
293
294 if(check_expr->expr_type != ASN_BASIC_INTEGER
295 || check_expr->meta_type != AMT_VALUE) {
296 fprintf(stderr,
297 "CHECKER: Unsupported type of \"%s\" value: "
298 "%d at line %d of %s\n",
299 check_expr->Identifier,
300 check_expr->expr_type,
301 check_expr->_lineno,
302 mod->source_file_name
303 );
304 return -1;
305 }
306
307 assert(check_expr->meta_type == AMT_VALUE);
308
309 value = check_expr->value;
310 if(value == NULL || value->type != ATV_INTEGER) {
311 fprintf(stderr,
312 "CHECKER: Unsupported value type of \"%s\": "
313 "%d at line %d of %s\n",
314 check_expr->Identifier,
Lev Walkin409c44e2004-06-05 08:57:10 +0000315 value?(signed)value->type:-1,
Lev Walkinf15320b2004-06-03 03:38:44 +0000316 expr->_lineno,
317 mod->source_file_name
318 );
319 return -1;
320 }
321
322 name = check_expr->Identifier + sizeof("check-") - 1;
323
324 /*
325 * Scan in search for the original.
326 */
327 TQ_FOR(expr, &(mod->members), next) {
328 if(strcmp(expr->Identifier, name) == 0)
329 break;
330 }
331
332 if(expr == NULL) {
333 fprintf(stderr,
334 "CHECKER: Value \"%s\" requested by "
335 "\"check-%s\" at line %d of %s is not found!\n",
336 name, name, check_expr->_lineno,
337 mod->source_file_name
338 );
339 return -1;
340 }
341
342 if(0 && expr->expr_type != check_expr->expr_type) {
343 fprintf(stderr,
344 "CHECKER: Value type of \"%s\" (=%d) at line %d "
345 "does not have desired type %d as requested by "
346 "\"check-%s\" in %s\n",
347 expr->Identifier,
348 expr->expr_type,
349 expr->_lineno,
350 check_expr->expr_type,
351 name,
352 mod->source_file_name
353 );
354 return -1;
355 }
356
357 if(expr->value == NULL
358 || expr->value->type != value->type) {
359 fprintf(stderr,
360 "CHECKER: Value of \"%s\" (\"%s\", type=%d) at line %d "
361 "does not have desired type %d as requested by "
362 "\"check-%s\" in %s\n",
363 expr->Identifier,
364 asn1f_printable_value(expr->value),
365 expr->value->type,
366 expr->_lineno,
367 value->type,
368 name,
369 mod->source_file_name
370 );
371 return -1;
372 }
373
374 assert(value->type = ATV_INTEGER);
375
376 return 0;
377}
378
379