blob: 6f5f25e60eb275d0833e581ece6ba0d57d216240 [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 Walkinc0e03b92017-08-22 01:48:23 -070013#include <libgen.h>
Lev Walkinf15320b2004-06-03 03:38:44 +000014
15#include "asn1fix.h"
Lev Walkinc0e03b92017-08-22 01:48:23 -070016#include "asn1_buffer.h"
17#include "asn1_namespace.h"
Lev Walkinf15320b2004-06-03 03:38:44 +000018
Lev Walkine0d321a2014-09-11 01:28:57 -070019#ifndef TOP_SRCDIR
20#define TOP_SRCDIR_S ".."
21#else
22#define STRINGIFY_MACRO2(x) #x
23#define STRINGIFY_MACRO(x) STRINGIFY_MACRO2(x)
24#define TOP_SRCDIR_S STRINGIFY_MACRO(TOP_SRCDIR)
25#endif
26
Lev Walkin55982b82016-03-14 03:56:16 -070027static int check(const char *fname,
Lev Walkinf15320b2004-06-03 03:38:44 +000028 enum asn1p_flags parser_flags,
29 enum asn1f_flags fixer_flags);
30static int post_fix_check(asn1p_t *asn);
31static int post_fix_check_element(asn1p_module_t *mod, asn1p_expr_t *expr);
32
33int
34main(int ac, char **av) {
Lev Walkin93659562010-11-20 09:47:13 -080035#ifdef _WIN32
Lev Walkin4efbfb72005-02-25 14:20:30 +000036 intptr_t dir;
37 struct _finddata_t c_file;
38#else
Lev Walkinf15320b2004-06-03 03:38:44 +000039 struct dirent *dp;
40 DIR *dir;
Lev Walkin4efbfb72005-02-25 14:20:30 +000041#endif
Lev Walkinf15320b2004-06-03 03:38:44 +000042 int failed = 0;
43 int completed = 0;
44 enum asn1p_flags parser_flags = A1P_NOFLAGS;
45 enum asn1f_flags fixer_flags = A1F_NOFLAGS;
Lev Walkin4efbfb72005-02-25 14:20:30 +000046 const char *filename;
Lev Walkin07721d52005-02-25 14:35:02 +000047 size_t len;
Lev Walkinf15320b2004-06-03 03:38:44 +000048
49 /*
50 * Just in case when one decides that some flags better be
51 * enabled during `ASN1_FIXER_FLAGS=1 make check` or some
52 * similar usage.
53 */
54 if(getenv("ASN1_PARSER_FLAGS"))
55 parser_flags = atoi(getenv("ASN1_PARSER_FLAGS"));
56 if(getenv("ASN1_FIXER_FLAGS"))
57 fixer_flags = atoi(getenv("ASN1_FIXER_FLAGS"));
58
59 /*
60 * Go into a directory with tests.
61 */
62 if(ac <= 1) {
Lev Walkinc0e03b92017-08-22 01:48:23 -070063 abuf *asn1_tests_dirname = abuf_new();
64 const char *top_srcdir = getenv("top_srcdir");
65 if(!top_srcdir) top_srcdir = TOP_SRCDIR_S;
66
67 abuf_printf(asn1_tests_dirname, "%s/tests/tests-asn1c-compiler",
68 top_srcdir);
69
70 fprintf(stderr, "Testing in %s...\n", top_srcdir);
Lev Walkin22256742017-10-08 16:33:57 -070071 int ret = chdir(asn1_tests_dirname->buffer);
Lev Walkin08068b22016-01-24 22:49:06 -080072 if(ret == -1)
Lev Walkinc0e03b92017-08-22 01:48:23 -070073 fprintf(stderr, "%s: %s\n", asn1_tests_dirname->buffer,
74 strerror(errno));
Lev Walkin08068b22016-01-24 22:49:06 -080075 assert(ret == 0);
Lev Walkin9e66d162016-03-14 03:36:35 -070076 /* For some reasons, tests could be hidden under extra tests dir. */
Lev Walkin93659562010-11-20 09:47:13 -080077#ifdef _WIN32
Lev Walkin4efbfb72005-02-25 14:20:30 +000078 dir = _findfirst("*.asn1", &c_file);
79 assert(dir != -1L);
80#else
Lev Walkinf15320b2004-06-03 03:38:44 +000081 dir = opendir(".");
82 assert(dir);
Lev Walkin93659562010-11-20 09:47:13 -080083#endif /* _WIN32 */
Lev Walkinf15320b2004-06-03 03:38:44 +000084 } else {
85 dir = 0;
86 }
87
88 /*
89 * Scan every *.asn1 file and try to parse and fix it.
90 */
Lev Walkin22256742017-10-08 16:33:57 -070091 if(dir) {
Lev Walkin93659562010-11-20 09:47:13 -080092#ifdef _WIN32
Lev Walkin22256742017-10-08 16:33:57 -070093 do {
94 filename = c_file.name;
Lev Walkin4efbfb72005-02-25 14:20:30 +000095#else
Lev Walkin22256742017-10-08 16:33:57 -070096 while((dp = readdir(dir))) {
97 filename = dp->d_name;
Lev Walkin93659562010-11-20 09:47:13 -080098#endif /* _WIN32 */
Lev Walkin22256742017-10-08 16:33:57 -070099 len = strlen(filename);
100 if(len <= 5 || !isdigit(filename[0])
101 || strcmp(filename + len - 5, ".asn1"))
102 continue;
103 int ret = check(filename, parser_flags, fixer_flags);
104 if(ret) {
105 fprintf(stderr, "FAILED: %s\n", filename);
106 failed++;
107 }
108 completed++;
Lev Walkin93659562010-11-20 09:47:13 -0800109#ifdef _WIN32
Lev Walkin22256742017-10-08 16:33:57 -0700110 } while(_findnext(dir, &c_file) == 0);
111 _findclose(dir);
Lev Walkin4efbfb72005-02-25 14:20:30 +0000112#else
Lev Walkin22256742017-10-08 16:33:57 -0700113 }
114 closedir(dir);
Lev Walkin93659562010-11-20 09:47:13 -0800115#endif /* _WIN32 */
Lev Walkin4efbfb72005-02-25 14:20:30 +0000116
Lev Walkinf15320b2004-06-03 03:38:44 +0000117
Lev Walkin22256742017-10-08 16:33:57 -0700118 fprintf(stderr,
119 "Tests COMPLETED: %d\n"
120 "Tests FAILED: %d\n",
121 completed, failed);
122 } else {
123 for(int i = 1; i < ac; i++) {
124 int ret = check(av[i], parser_flags, fixer_flags);
125 if(ret) {
126 fprintf(stderr, "FAILED: %s\n", av[i]);
127 failed++;
128 }
129 completed++;
130 }
131 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000132
Lev Walkin22256742017-10-08 16:33:57 -0700133 if(completed == 0) {
134 fprintf(stderr, "No tests defined?!\n");
135 exit(EX_NOINPUT);
136 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000137
Lev Walkin22256742017-10-08 16:33:57 -0700138 if(failed) {
139 exit(EX_DATAERR);
140 }
141 return 0;
Lev Walkinf15320b2004-06-03 03:38:44 +0000142}
143
144static int
Lev Walkin55982b82016-03-14 03:56:16 -0700145check(const char *fname,
Lev Walkinf15320b2004-06-03 03:38:44 +0000146 enum asn1p_flags parser_flags,
147 enum asn1f_flags fixer_flags) {
148 asn1p_t *asn;
149 int expected_parseable; /* Is it expected to be parseable? */
150 int expected_fix_code; /* What code a fixer must return */
151 int r_value = 0;
152
153 /*
154 * Figure out how the processing should go by inferring
155 * expectations from the file name.
156 */
157 if(strstr(fname, "-OK.")) {
158 expected_parseable = 1;
159 expected_fix_code = 0;
160 } else if(strstr(fname, "-NP.")) {
161 expected_parseable = 0;
162 expected_fix_code = 123; /* Does not matter */
163 } else if(strstr(fname, "-SE.")) {
164 expected_parseable = 1;
165 expected_fix_code = -1; /* Semantically incorrect */
166 } else if(strstr(fname, "-SW.")) {
167 expected_parseable = 1;
168 expected_fix_code = 1; /* Semantically suspicious */
169 } else {
170 fprintf(stderr, "%s: Invalid file name format\n", fname);
171 return -1;
172 }
173
Lev Walkin4b553412005-08-14 14:45:44 +0000174 /* Flag modifiers */
175 if(strstr(fname, "-blessSize-"))
176 fixer_flags |= A1F_EXTENDED_SizeConstraint;
177
Lev Walkinf15320b2004-06-03 03:38:44 +0000178 fprintf(stderr, "[=> %s]\n", fname);
179
180 /*
181 * Perform low-level parsing.
182 */
183 if(!expected_parseable)
184 fprintf(stderr, "Expecting error...\n");
185 asn = asn1p_parse_file(fname, parser_flags);
186 if(asn == NULL) {
187 if(expected_parseable) {
188 fprintf(stderr, "Cannot parse file \"%s\"\n", fname);
189 r_value = -1;
190 } else {
191 fprintf(stderr,
192 "Previous error is EXPECTED, no worry\n");
193 }
194 } else if(!expected_parseable) {
195 fprintf(stderr,
196 "The file \"%s\" is not expected to be parseable, "
197 "yet parsing was successfull!\n", fname);
198 r_value = -1;
199 }
Lev Walkin6b3ff542006-03-06 14:51:00 +0000200 if(!asn) return r_value;
201
202 if(r_value == 0) {
Lev Walkinc0e03b92017-08-22 01:48:23 -0700203 char *fname_copy = strdup(fname);
204 char *test_dir = dirname(fname_copy);
205 abuf *skeletons_dirname = abuf_new();
Lev Walkin6b3ff542006-03-06 14:51:00 +0000206 asn1p_t *std_asn;
Lev Walkinc0e03b92017-08-22 01:48:23 -0700207
208 abuf_printf(skeletons_dirname,
209 "%s/../../skeletons/standard-modules/"
210 "ASN1C-UsefulInformationObjectClasses.asn1",
211 test_dir);
212 free(fname_copy);
213
214 std_asn = asn1p_parse_file(skeletons_dirname->buffer, A1P_NOFLAGS);
215 if(std_asn) {
Lev Walkin6b3ff542006-03-06 14:51:00 +0000216 asn1p_module_t *mod;
Lev Walkin9c2285a2006-03-09 08:49:26 +0000217 while((mod = TQ_REMOVE(&(std_asn->modules), mod_next))) {
218 mod->_tags |= MT_STANDARD_MODULE;
Lev Walkin6b3ff542006-03-06 14:51:00 +0000219 TQ_ADD(&(asn->modules), mod, mod_next);
Lev Walkin9c2285a2006-03-09 08:49:26 +0000220 }
Lev Walkin223000a2006-09-13 00:21:58 +0000221 asn1p_delete(std_asn);
Lev Walkinc0e03b92017-08-22 01:48:23 -0700222
223 /* Allow referencing imported modules. */
224 asn1f_use_standard_namespaces(asn);
225 } else {
226 fprintf(stderr, "%s: %s\n", skeletons_dirname->buffer,
227 strerror(errno));
228 }
229
230 abuf_free(skeletons_dirname);
231 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000232
233 /*
234 * Perform semantical checks and fixes.
235 */
Lev Walkin6b3ff542006-03-06 14:51:00 +0000236 if(r_value == 0) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000237 int ret;
238
239 if(expected_fix_code)
240 fprintf(stderr, "Expecting some problems...\n");
241
242 ret = asn1f_process(asn, fixer_flags, 0);
243 if(ret) {
244 if(ret == expected_fix_code) {
245 fprintf(stderr,
246 "Previous error is EXPECTED, "
247 "no worry\n");
248 } else {
249 fprintf(stderr,
250 "Cannot process file \"%s\": %d\n",
251 fname, ret);
252 r_value = -1;
253 }
254 } else if(ret != expected_fix_code) {
255 fprintf(stderr,
256 "File \"%s\" is expected "
257 "to be semantically incorrect, "
258 "yet processing was successful!\n",
259 fname);
260 r_value = -1;
261 }
262 }
263
264 /*
265 * Check validity of some values, if grammar has special
266 * instructions for that.
267 */
Lev Walkin6b3ff542006-03-06 14:51:00 +0000268 if(r_value == 0) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000269 if(post_fix_check(asn))
270 r_value = -1;
271 }
272
273 /*
Lev Walkin6b3ff542006-03-06 14:51:00 +0000274 * Destroy the asn.
Lev Walkinf15320b2004-06-03 03:38:44 +0000275 */
Lev Walkin55f106a2006-09-15 16:34:12 +0000276#ifdef CLEAN_EVERYTHING
Lev Walkin223000a2006-09-13 00:21:58 +0000277 asn1p_delete(asn);
Lev Walkin55f106a2006-09-15 16:34:12 +0000278#endif
Lev Walkinf15320b2004-06-03 03:38:44 +0000279
280 return r_value;
281}
282
283
284static int
285post_fix_check(asn1p_t *asn) {
286 asn1p_module_t *mod;
287 asn1p_expr_t *expr;
288 int r_value = 0;
289
290 TQ_FOR(mod, &(asn->modules), mod_next) {
291 TQ_FOR(expr, &(mod->members), next) {
292 assert(expr->Identifier);
293 if(strncmp(expr->Identifier, "check-", 6) == 0) {
294 if(post_fix_check_element(mod, expr))
295 r_value = -1;
296 }
297 }
298 }
299
300 return r_value;
301}
302
303
304static int
305post_fix_check_element(asn1p_module_t *mod, asn1p_expr_t *check_expr) {
306 asn1p_expr_t *expr = NULL;
307 char *name;
308 asn1p_value_t *value;
309
310 if(check_expr->expr_type != ASN_BASIC_INTEGER
311 || check_expr->meta_type != AMT_VALUE) {
312 fprintf(stderr,
313 "CHECKER: Unsupported type of \"%s\" value: "
314 "%d at line %d of %s\n",
315 check_expr->Identifier,
316 check_expr->expr_type,
317 check_expr->_lineno,
318 mod->source_file_name
319 );
320 return -1;
321 }
322
323 assert(check_expr->meta_type == AMT_VALUE);
324
325 value = check_expr->value;
326 if(value == NULL || value->type != ATV_INTEGER) {
327 fprintf(stderr,
328 "CHECKER: Unsupported value type of \"%s\": "
329 "%d at line %d of %s\n",
330 check_expr->Identifier,
Lev Walkin409c44e2004-06-05 08:57:10 +0000331 value?(signed)value->type:-1,
Lev Walkinf15320b2004-06-03 03:38:44 +0000332 expr->_lineno,
333 mod->source_file_name
334 );
335 return -1;
336 }
337
338 name = check_expr->Identifier + sizeof("check-") - 1;
339
340 /*
341 * Scan in search for the original.
342 */
343 TQ_FOR(expr, &(mod->members), next) {
344 if(strcmp(expr->Identifier, name) == 0)
345 break;
346 }
347
348 if(expr == NULL) {
349 fprintf(stderr,
350 "CHECKER: Value \"%s\" requested by "
351 "\"check-%s\" at line %d of %s is not found!\n",
352 name, name, check_expr->_lineno,
353 mod->source_file_name
354 );
355 return -1;
356 }
357
358 if(0 && expr->expr_type != check_expr->expr_type) {
359 fprintf(stderr,
360 "CHECKER: Value type of \"%s\" (=%d) at line %d "
361 "does not have desired type %d as requested by "
362 "\"check-%s\" in %s\n",
363 expr->Identifier,
364 expr->expr_type,
365 expr->_lineno,
366 check_expr->expr_type,
367 name,
368 mod->source_file_name
369 );
370 return -1;
371 }
372
373 if(expr->value == NULL
374 || expr->value->type != value->type) {
375 fprintf(stderr,
376 "CHECKER: Value of \"%s\" (\"%s\", type=%d) at line %d "
377 "does not have desired type %d as requested by "
378 "\"check-%s\" in %s\n",
379 expr->Identifier,
380 asn1f_printable_value(expr->value),
381 expr->value->type,
382 expr->_lineno,
383 value->type,
384 name,
385 mod->source_file_name
386 );
387 return -1;
388 }
389
Lev Walkinf15320b2004-06-03 03:38:44 +0000390 return 0;
391}
392
393