blob: b71a8c9ec040b54b93904a38293894ce2b5ed511 [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
Lev Walkin1a49ced2017-11-06 00:07:00 -080015#include "genhash.h"
Lev Walkinf15320b2004-06-03 03:38:44 +000016#include "asn1fix.h"
Lev Walkinc0e03b92017-08-22 01:48:23 -070017#include "asn1_buffer.h"
18#include "asn1_namespace.h"
Lev Walkinf15320b2004-06-03 03:38:44 +000019
Lev Walkine0d321a2014-09-11 01:28:57 -070020#ifndef TOP_SRCDIR
21#define TOP_SRCDIR_S ".."
22#else
23#define STRINGIFY_MACRO2(x) #x
24#define STRINGIFY_MACRO(x) STRINGIFY_MACRO2(x)
25#define TOP_SRCDIR_S STRINGIFY_MACRO(TOP_SRCDIR)
26#endif
27
Lev Walkin55982b82016-03-14 03:56:16 -070028static int check(const char *fname,
Lev Walkinf15320b2004-06-03 03:38:44 +000029 enum asn1p_flags parser_flags,
30 enum asn1f_flags fixer_flags);
31static int post_fix_check(asn1p_t *asn);
32static int post_fix_check_element(asn1p_module_t *mod, asn1p_expr_t *expr);
33
34int
35main(int ac, char **av) {
Lev Walkin93659562010-11-20 09:47:13 -080036#ifdef _WIN32
Lev Walkin4efbfb72005-02-25 14:20:30 +000037 intptr_t dir;
38 struct _finddata_t c_file;
39#else
Lev Walkinf15320b2004-06-03 03:38:44 +000040 struct dirent *dp;
41 DIR *dir;
Lev Walkin4efbfb72005-02-25 14:20:30 +000042#endif
Lev Walkinf15320b2004-06-03 03:38:44 +000043 int failed = 0;
44 int completed = 0;
45 enum asn1p_flags parser_flags = A1P_NOFLAGS;
46 enum asn1f_flags fixer_flags = A1F_NOFLAGS;
Lev Walkin4efbfb72005-02-25 14:20:30 +000047 const char *filename;
Lev Walkin07721d52005-02-25 14:35:02 +000048 size_t len;
Lev Walkinf15320b2004-06-03 03:38:44 +000049
50 /*
51 * Just in case when one decides that some flags better be
52 * enabled during `ASN1_FIXER_FLAGS=1 make check` or some
53 * similar usage.
54 */
55 if(getenv("ASN1_PARSER_FLAGS"))
56 parser_flags = atoi(getenv("ASN1_PARSER_FLAGS"));
57 if(getenv("ASN1_FIXER_FLAGS"))
58 fixer_flags = atoi(getenv("ASN1_FIXER_FLAGS"));
59
60 /*
61 * Go into a directory with tests.
62 */
63 if(ac <= 1) {
Lev Walkinc0e03b92017-08-22 01:48:23 -070064 abuf *asn1_tests_dirname = abuf_new();
65 const char *top_srcdir = getenv("top_srcdir");
66 if(!top_srcdir) top_srcdir = TOP_SRCDIR_S;
67
68 abuf_printf(asn1_tests_dirname, "%s/tests/tests-asn1c-compiler",
69 top_srcdir);
70
71 fprintf(stderr, "Testing in %s...\n", top_srcdir);
Lev Walkin22256742017-10-08 16:33:57 -070072 int ret = chdir(asn1_tests_dirname->buffer);
Lev Walkin08068b22016-01-24 22:49:06 -080073 if(ret == -1)
Lev Walkinc0e03b92017-08-22 01:48:23 -070074 fprintf(stderr, "%s: %s\n", asn1_tests_dirname->buffer,
75 strerror(errno));
Lev Walkin08068b22016-01-24 22:49:06 -080076 assert(ret == 0);
Lev Walkin9e66d162016-03-14 03:36:35 -070077 /* For some reasons, tests could be hidden under extra tests dir. */
Lev Walkin93659562010-11-20 09:47:13 -080078#ifdef _WIN32
Lev Walkin4efbfb72005-02-25 14:20:30 +000079 dir = _findfirst("*.asn1", &c_file);
80 assert(dir != -1L);
81#else
Lev Walkinf15320b2004-06-03 03:38:44 +000082 dir = opendir(".");
83 assert(dir);
Lev Walkin93659562010-11-20 09:47:13 -080084#endif /* _WIN32 */
Lev Walkinf15320b2004-06-03 03:38:44 +000085 } else {
86 dir = 0;
87 }
88
89 /*
90 * Scan every *.asn1 file and try to parse and fix it.
91 */
Lev Walkin22256742017-10-08 16:33:57 -070092 if(dir) {
Lev Walkin93659562010-11-20 09:47:13 -080093#ifdef _WIN32
Lev Walkin22256742017-10-08 16:33:57 -070094 do {
95 filename = c_file.name;
Lev Walkin4efbfb72005-02-25 14:20:30 +000096#else
Lev Walkin22256742017-10-08 16:33:57 -070097 while((dp = readdir(dir))) {
98 filename = dp->d_name;
Lev Walkin93659562010-11-20 09:47:13 -080099#endif /* _WIN32 */
Lev Walkin22256742017-10-08 16:33:57 -0700100 len = strlen(filename);
101 if(len <= 5 || !isdigit(filename[0])
102 || strcmp(filename + len - 5, ".asn1"))
103 continue;
104 int ret = check(filename, parser_flags, fixer_flags);
105 if(ret) {
106 fprintf(stderr, "FAILED: %s\n", filename);
107 failed++;
108 }
109 completed++;
Lev Walkin93659562010-11-20 09:47:13 -0800110#ifdef _WIN32
Lev Walkin22256742017-10-08 16:33:57 -0700111 } while(_findnext(dir, &c_file) == 0);
112 _findclose(dir);
Lev Walkin4efbfb72005-02-25 14:20:30 +0000113#else
Lev Walkin22256742017-10-08 16:33:57 -0700114 }
115 closedir(dir);
Lev Walkin93659562010-11-20 09:47:13 -0800116#endif /* _WIN32 */
Lev Walkin4efbfb72005-02-25 14:20:30 +0000117
Lev Walkinf15320b2004-06-03 03:38:44 +0000118
Lev Walkin22256742017-10-08 16:33:57 -0700119 fprintf(stderr,
120 "Tests COMPLETED: %d\n"
121 "Tests FAILED: %d\n",
122 completed, failed);
123 } else {
124 for(int i = 1; i < ac; i++) {
125 int ret = check(av[i], parser_flags, fixer_flags);
126 if(ret) {
127 fprintf(stderr, "FAILED: %s\n", av[i]);
128 failed++;
129 }
130 completed++;
131 }
132 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000133
Lev Walkin22256742017-10-08 16:33:57 -0700134 if(completed == 0) {
135 fprintf(stderr, "No tests defined?!\n");
136 exit(EX_NOINPUT);
137 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000138
Lev Walkin22256742017-10-08 16:33:57 -0700139 if(failed) {
140 exit(EX_DATAERR);
141 }
142 return 0;
Lev Walkinf15320b2004-06-03 03:38:44 +0000143}
144
145static int
Lev Walkin55982b82016-03-14 03:56:16 -0700146check(const char *fname,
Lev Walkinf15320b2004-06-03 03:38:44 +0000147 enum asn1p_flags parser_flags,
148 enum asn1f_flags fixer_flags) {
149 asn1p_t *asn;
150 int expected_parseable; /* Is it expected to be parseable? */
151 int expected_fix_code; /* What code a fixer must return */
152 int r_value = 0;
153
154 /*
155 * Figure out how the processing should go by inferring
156 * expectations from the file name.
157 */
158 if(strstr(fname, "-OK.")) {
159 expected_parseable = 1;
160 expected_fix_code = 0;
161 } else if(strstr(fname, "-NP.")) {
162 expected_parseable = 0;
163 expected_fix_code = 123; /* Does not matter */
164 } else if(strstr(fname, "-SE.")) {
165 expected_parseable = 1;
166 expected_fix_code = -1; /* Semantically incorrect */
167 } else if(strstr(fname, "-SW.")) {
168 expected_parseable = 1;
169 expected_fix_code = 1; /* Semantically suspicious */
170 } else {
171 fprintf(stderr, "%s: Invalid file name format\n", fname);
172 return -1;
173 }
174
Lev Walkin4b553412005-08-14 14:45:44 +0000175 /* Flag modifiers */
176 if(strstr(fname, "-blessSize-"))
177 fixer_flags |= A1F_EXTENDED_SizeConstraint;
178
Lev Walkinf15320b2004-06-03 03:38:44 +0000179 fprintf(stderr, "[=> %s]\n", fname);
180
181 /*
182 * Perform low-level parsing.
183 */
184 if(!expected_parseable)
185 fprintf(stderr, "Expecting error...\n");
186 asn = asn1p_parse_file(fname, parser_flags);
187 if(asn == NULL) {
188 if(expected_parseable) {
189 fprintf(stderr, "Cannot parse file \"%s\"\n", fname);
190 r_value = -1;
191 } else {
192 fprintf(stderr,
193 "Previous error is EXPECTED, no worry\n");
194 }
195 } else if(!expected_parseable) {
196 fprintf(stderr,
197 "The file \"%s\" is not expected to be parseable, "
198 "yet parsing was successfull!\n", fname);
199 r_value = -1;
200 }
Lev Walkin6b3ff542006-03-06 14:51:00 +0000201 if(!asn) return r_value;
202
203 if(r_value == 0) {
Lev Walkinc0e03b92017-08-22 01:48:23 -0700204 char *fname_copy = strdup(fname);
205 char *test_dir = dirname(fname_copy);
206 abuf *skeletons_dirname = abuf_new();
Lev Walkin6b3ff542006-03-06 14:51:00 +0000207 asn1p_t *std_asn;
Lev Walkinc0e03b92017-08-22 01:48:23 -0700208
209 abuf_printf(skeletons_dirname,
210 "%s/../../skeletons/standard-modules/"
211 "ASN1C-UsefulInformationObjectClasses.asn1",
212 test_dir);
213 free(fname_copy);
214
215 std_asn = asn1p_parse_file(skeletons_dirname->buffer, A1P_NOFLAGS);
216 if(std_asn) {
Lev Walkin6b3ff542006-03-06 14:51:00 +0000217 asn1p_module_t *mod;
Lev Walkin9c2285a2006-03-09 08:49:26 +0000218 while((mod = TQ_REMOVE(&(std_asn->modules), mod_next))) {
219 mod->_tags |= MT_STANDARD_MODULE;
Lev Walkin6b3ff542006-03-06 14:51:00 +0000220 TQ_ADD(&(asn->modules), mod, mod_next);
Lev Walkin9c2285a2006-03-09 08:49:26 +0000221 }
Lev Walkin223000a2006-09-13 00:21:58 +0000222 asn1p_delete(std_asn);
Lev Walkinc0e03b92017-08-22 01:48:23 -0700223
224 /* Allow referencing imported modules. */
225 asn1f_use_standard_namespaces(asn);
226 } else {
227 fprintf(stderr, "%s: %s\n", skeletons_dirname->buffer,
228 strerror(errno));
229 }
230
231 abuf_free(skeletons_dirname);
232 }
Lev Walkinf15320b2004-06-03 03:38:44 +0000233
234 /*
235 * Perform semantical checks and fixes.
236 */
Lev Walkin6b3ff542006-03-06 14:51:00 +0000237 if(r_value == 0) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000238 int ret;
239
240 if(expected_fix_code)
241 fprintf(stderr, "Expecting some problems...\n");
242
243 ret = asn1f_process(asn, fixer_flags, 0);
244 if(ret) {
245 if(ret == expected_fix_code) {
246 fprintf(stderr,
247 "Previous error is EXPECTED, "
248 "no worry\n");
249 } else {
250 fprintf(stderr,
251 "Cannot process file \"%s\": %d\n",
252 fname, ret);
253 r_value = -1;
254 }
255 } else if(ret != expected_fix_code) {
256 fprintf(stderr,
257 "File \"%s\" is expected "
258 "to be semantically incorrect, "
259 "yet processing was successful!\n",
260 fname);
261 r_value = -1;
262 }
263 }
264
265 /*
266 * Check validity of some values, if grammar has special
267 * instructions for that.
268 */
Lev Walkin6b3ff542006-03-06 14:51:00 +0000269 if(r_value == 0) {
Lev Walkinf15320b2004-06-03 03:38:44 +0000270 if(post_fix_check(asn))
271 r_value = -1;
272 }
273
274 /*
Lev Walkin6b3ff542006-03-06 14:51:00 +0000275 * Destroy the asn.
Lev Walkinf15320b2004-06-03 03:38:44 +0000276 */
Lev Walkin55f106a2006-09-15 16:34:12 +0000277#ifdef CLEAN_EVERYTHING
Lev Walkin223000a2006-09-13 00:21:58 +0000278 asn1p_delete(asn);
Lev Walkin55f106a2006-09-15 16:34:12 +0000279#endif
Lev Walkinf15320b2004-06-03 03:38:44 +0000280
281 return r_value;
282}
283
284
285static int
286post_fix_check(asn1p_t *asn) {
287 asn1p_module_t *mod;
288 asn1p_expr_t *expr;
289 int r_value = 0;
290
291 TQ_FOR(mod, &(asn->modules), mod_next) {
292 TQ_FOR(expr, &(mod->members), next) {
293 assert(expr->Identifier);
294 if(strncmp(expr->Identifier, "check-", 6) == 0) {
295 if(post_fix_check_element(mod, expr))
296 r_value = -1;
297 }
298 }
299 }
300
301 return r_value;
302}
303
304
305static int
306post_fix_check_element(asn1p_module_t *mod, asn1p_expr_t *check_expr) {
307 asn1p_expr_t *expr = NULL;
308 char *name;
309 asn1p_value_t *value;
310
311 if(check_expr->expr_type != ASN_BASIC_INTEGER
312 || check_expr->meta_type != AMT_VALUE) {
313 fprintf(stderr,
314 "CHECKER: Unsupported type of \"%s\" value: "
315 "%d at line %d of %s\n",
316 check_expr->Identifier,
317 check_expr->expr_type,
318 check_expr->_lineno,
319 mod->source_file_name
320 );
321 return -1;
322 }
323
324 assert(check_expr->meta_type == AMT_VALUE);
325
326 value = check_expr->value;
327 if(value == NULL || value->type != ATV_INTEGER) {
328 fprintf(stderr,
329 "CHECKER: Unsupported value type of \"%s\": "
330 "%d at line %d of %s\n",
331 check_expr->Identifier,
Lev Walkin409c44e2004-06-05 08:57:10 +0000332 value?(signed)value->type:-1,
Lev Walkinf15320b2004-06-03 03:38:44 +0000333 expr->_lineno,
334 mod->source_file_name
335 );
336 return -1;
337 }
338
339 name = check_expr->Identifier + sizeof("check-") - 1;
340
341 /*
342 * Scan in search for the original.
343 */
Lev Walkin1a49ced2017-11-06 00:07:00 -0800344 expr = genhash_get(mod->members_hash, name);
Lev Walkinf15320b2004-06-03 03:38:44 +0000345 if(expr == NULL) {
346 fprintf(stderr,
347 "CHECKER: Value \"%s\" requested by "
348 "\"check-%s\" at line %d of %s is not found!\n",
349 name, name, check_expr->_lineno,
350 mod->source_file_name
351 );
352 return -1;
353 }
354
355 if(0 && expr->expr_type != check_expr->expr_type) {
356 fprintf(stderr,
357 "CHECKER: Value type of \"%s\" (=%d) at line %d "
358 "does not have desired type %d as requested by "
359 "\"check-%s\" in %s\n",
360 expr->Identifier,
361 expr->expr_type,
362 expr->_lineno,
363 check_expr->expr_type,
364 name,
365 mod->source_file_name
366 );
367 return -1;
368 }
369
370 if(expr->value == NULL
371 || expr->value->type != value->type) {
372 fprintf(stderr,
373 "CHECKER: Value of \"%s\" (\"%s\", type=%d) at line %d "
374 "does not have desired type %d as requested by "
375 "\"check-%s\" in %s\n",
376 expr->Identifier,
377 asn1f_printable_value(expr->value),
378 expr->value->type,
379 expr->_lineno,
380 value->type,
381 name,
382 mod->source_file_name
383 );
384 return -1;
385 }
386
Lev Walkinf15320b2004-06-03 03:38:44 +0000387 return 0;
388}
389
390