NativeEnumerated.c vars NULL init and check
[com/asn1c.git] / tests / tests-c-compiler / check-src / check-126.-gen-PER.c
1 /*
2  * Mode of operation:
3  * Each of the *.in files is XER-decoded, then converted into PER,
4  * compared with *.out file, then decoded and compared with the original.
5  */
6 #undef  NDEBUG
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <sys/types.h>
10 #include <unistd.h>     /* for chdir(2) */
11 #include <string.h>
12 #include <dirent.h>
13 #include <assert.h>
14 #include <ctype.h>
15 #include <errno.h>
16
17 #include <PDU.h>
18
19 #ifndef SRCDIR
20 #define SRCDIR_S ".."
21 #else
22 #define STRINGIFY_MACRO2(x) #x
23 #define STRINGIFY_MACRO(x)  STRINGIFY_MACRO2(x)
24 #define SRCDIR_S    STRINGIFY_MACRO(SRCDIR)
25 #endif
26
27 static unsigned char buf[4096];
28 static int buf_offset;
29
30 static int
31 _buf_writer(const void *buffer, size_t size, void *app_key) {
32         (void)app_key;
33         assert(buf_offset + size < sizeof(buf));
34         memcpy(buf + buf_offset, buffer, size);
35 #ifdef ASN_EMIT_DEBUG
36         unsigned char *b, *bend;
37         b = buf + buf_offset;
38         bend = b + size;
39         fprintf(stderr, "=> [");
40         for(; b < bend; b++) {
41                 if(*b >= 32 && *b < 127 && *b != '%')
42                         fprintf(stderr, "%c", *b);
43                 else
44                         fprintf(stderr, "%%%02x", *b);
45         }
46         fprintf(stderr, "]:%zd\n", size);
47 #endif
48         buf_offset += size;
49         return 0;
50 }
51
52 enum enctype {
53         AS_PER,
54         AS_DER,
55         AS_XER,
56 };
57
58 static void
59 save_object_as(PDU_t *st, enum enctype how) {
60         asn_enc_rval_t rval; /* Return value */
61
62         buf_offset = 0;
63
64         /*
65          * Save object using specified method.
66          */
67         switch(how) {
68         case AS_PER:
69                 rval = uper_encode(&asn_DEF_PDU, 0, st, _buf_writer, 0);
70                 assert(rval.encoded > 0);
71                 fprintf(stderr, "SAVED OBJECT IN SIZE %d\n", buf_offset);
72                 return;
73         case AS_DER:
74                 rval = der_encode(&asn_DEF_PDU, st,
75                         _buf_writer, 0);
76                 break;
77         case AS_XER:
78                 rval = xer_encode(&asn_DEF_PDU, st, XER_F_BASIC,
79                         _buf_writer, 0);
80                 break;
81     default:
82         assert(!"Unreachable");
83         }
84
85         if (rval.encoded == -1) {
86                 fprintf(stderr,
87                         "Cannot encode %s: %s\n",
88                         rval.failed_type->name, strerror(errno));
89                 assert(rval.encoded != -1);
90                 return;
91         }
92
93         fprintf(stderr, "SAVED OBJECT IN SIZE %d\n", buf_offset);
94 }
95
96 static PDU_t *
97 load_object_from(const char *fname, unsigned char *fbuf, size_t size, enum enctype how, int mustfail) {
98         asn_dec_rval_t rval;
99         PDU_t *st = 0;
100         ssize_t csize = 1;
101
102         if(getenv("INITIAL_CHUNK_SIZE"))
103                 csize = atoi(getenv("INITIAL_CHUNK_SIZE"));
104
105         /* Perform multiple iterations with multiple chunks sizes */
106         for(; csize < 20; csize += 1) {
107                 int fbuf_offset = 0;
108                 int fbuf_left = size;
109                 int fbuf_chunk = csize;
110
111                 fprintf(stderr, "LOADING OBJECT OF SIZE %zd FROM [%s] as %s,"
112                         " chunks %zd\n",
113                         size, fname, how==AS_PER?"PER":"XER", csize);
114
115                 if(st) ASN_STRUCT_FREE(asn_DEF_PDU, st);
116                 st = 0;
117
118                 do {
119                         ASN_DEBUG("\nDecoding bytes %d..%d (left %d) [%s]",
120                                 fbuf_offset,
121                                         fbuf_chunk < fbuf_left
122                                                 ? fbuf_chunk : fbuf_left,
123                                         fbuf_left,
124                                 fname);
125 #ifdef  ASN_EMIT_DEBUG
126                         if(st) {
127                                 fprintf(stderr, "=== currently ===\n");
128                                 asn_fprint(stderr, &asn_DEF_PDU, st);
129                                 fprintf(stderr, "=== end ===\n");
130                         }
131 #endif
132                         switch(how) {
133                         case AS_XER:
134                                 rval = xer_decode(0, &asn_DEF_PDU, (void **)&st,
135                                         fbuf + fbuf_offset,
136                                         fbuf_chunk < fbuf_left 
137                                         ? fbuf_chunk : fbuf_left);
138                                 break;
139                         case AS_DER:
140                                 assert(0);
141                                 break;
142                         case AS_PER:
143                                 rval = uper_decode(0, &asn_DEF_PDU,
144                                         (void **)&st, fbuf + fbuf_offset,
145                                         fbuf_chunk < fbuf_left 
146                                         ? fbuf_chunk : fbuf_left, 0, 0);
147                                 if(rval.code == RC_WMORE) {
148                                         if(fbuf_chunk == fbuf_left) {
149                                                 fprintf(stderr, "-> PER decode error (%zd bits of %zd bytes (c=%d,l=%d)) \n", rval.consumed, size, fbuf_chunk, fbuf_left);
150                                                 rval.code = RC_FAIL;
151                                                 rval.consumed += 7;
152                                                 rval.consumed /= 8;
153                                                 if(mustfail) {
154                                                         fprintf(stderr, "-> (this was expected failure)\n");
155                                                         ASN_STRUCT_FREE(asn_DEF_PDU, st);
156                                                         return 0;
157                                                 }
158                                         } else {
159                                                 rval.consumed = 0; /* Not restartable */
160                                                 ASN_STRUCT_FREE(asn_DEF_PDU, st);
161                                                 st = 0;
162                                                 ASN_DEBUG("-> PER wants more");
163                                         }
164                                 } else {
165                                         ASN_DEBUG("-> PER ret %d/%zd mf=%d",
166                                                 rval.code, rval.consumed, mustfail);
167                                         /* uper_decode() returns _bits_ */
168                                         rval.consumed += 7;
169                                         rval.consumed /= 8;
170                                         if((mustfail?1:0) == (rval.code == RC_FAIL)) {
171                                                 if(mustfail) {
172                                                         fprintf(stderr, "-> (this was expected failure)\n");
173                                                         ASN_STRUCT_FREE(asn_DEF_PDU, st);
174                                                         return 0;
175                                                 }
176                                         } else {
177                                                 fprintf(stderr, "-> (unexpected %s)\n", mustfail ? "success" : "failure");
178                                                 rval.code = RC_FAIL;
179                                         }
180                                 }
181                                 break;
182             default:
183                 assert(!"Unreachable");
184                         }
185                         fbuf_offset += rval.consumed;
186                         fbuf_left -= rval.consumed;
187                         if(rval.code == RC_WMORE)
188                                 fbuf_chunk += 1;        /* Give little more */
189                         else
190                                 fbuf_chunk = csize;     /* Back off */
191                 } while(fbuf_left && rval.code == RC_WMORE);
192
193                 assert(rval.code == RC_OK);
194                 if(how == AS_PER) {
195                         fprintf(stderr, "[left %d, off %d, size %zd]\n",
196                                 fbuf_left, fbuf_offset, size);
197                         assert(fbuf_offset == (ssize_t)size);
198                 } else {
199                         assert((fbuf_offset + 1 /* "\n" */  == (ssize_t)size
200                                 && fbuf[size - 1] == '\n')
201                         || (fbuf_offset + 2 /* "\r\n" */  == (ssize_t)size
202                                 && fbuf[size - 2] == '\r'
203                                 && fbuf[size - 1] == '\n')
204                         );
205                 }
206         }
207
208         if(st) asn_fprint(stderr, &asn_DEF_PDU, st);
209         return st;
210 }
211
212 static int
213 xer_encoding_equal(void *obufp, size_t osize, void *nbufp, size_t nsize) {
214     char *obuf = obufp;
215     char *nbuf = nbufp;
216         char *oend = obuf + osize;
217         char *nend = nbuf + nsize;
218
219         if((osize && !nsize) || (!osize && nsize))
220                 return 0;       /* not equal apriori */
221
222         while(1) {
223                 while(obuf < oend && isspace(*obuf)) obuf++;
224                 while(nbuf < nend && isspace(*nbuf)) nbuf++;
225
226                 if(obuf == oend || nbuf == nend) {
227                         if(obuf == oend && nbuf == nend)
228                                 break;
229                         fprintf(stderr, "%s data in reconstructed encoding\n",
230                                 (obuf == oend) ? "More" : "Less");
231                         return 0;
232                 }
233
234                 if(*obuf != *nbuf) {
235                         printf("%c%c != %c%c\n",
236                                 obuf[0], obuf[1],
237                                 nbuf[0], nbuf[1]);
238                         return 0;
239                 }
240                 obuf++, nbuf++;
241         }
242
243         return 1;
244 }
245
246 static void
247 compare_with_data_out(const char *fname, void *datap, size_t size) {
248     char *data = datap;
249         char outName[sizeof(SRCDIR_S) + 256];
250         unsigned char fbuf[1024];
251         size_t rd;
252         FILE *f;
253         char lastChar;
254         int mustfail, compare;
255         PDU_t *st;
256
257         sprintf(outName, SRCDIR_S "/data-126/%s", fname);
258         strcpy(outName + strlen(outName) - 3, ".out");
259
260         fprintf(stderr, "Comparing PER output with [%s]\n", outName);
261
262         lastChar = outName[strlen(outName)-5];
263         mustfail = lastChar == 'P';
264         compare = lastChar != 'C';
265
266         if((compare && !mustfail) && getenv("REGENERATE")) {
267                 f = fopen(outName, "w");
268                 fwrite(data, 1, size, f);
269                 fclose(f);
270         } else {
271                 f = fopen(outName, "r");
272                 assert(f);
273                 rd = fread(fbuf, 1, sizeof(fbuf), f);
274                 assert(rd);
275                 fclose(f);
276
277                 fprintf(stderr, "Trying to decode [%s]\n", outName);
278                 st = load_object_from(outName, fbuf, rd, AS_PER, mustfail);
279                 ASN_STRUCT_FREE(asn_DEF_PDU, st);
280                 if(mustfail) return;
281
282                 if(compare) {
283                         assert(rd == (size_t)size);
284                         assert(memcmp(fbuf, data, rd) == 0);
285                         fprintf(stderr, "XER->PER recoding .in->.out match.\n");
286                 } else {
287                         assert(rd != (size_t)size || memcmp(fbuf, data, rd));
288                         fprintf(stderr, "XER->PER recoding .in->.out diverge.\n");
289                 }
290         }
291 }
292
293 static void
294 process_XER_data(const char *fname, unsigned char *fbuf, size_t size) {
295         PDU_t *st;
296
297         st = load_object_from(fname, fbuf, size, AS_XER, 0);
298         if(!st) return;
299
300         /* Save and re-load as PER */
301         save_object_as(st, AS_PER);
302         ASN_STRUCT_FREE(asn_DEF_PDU, st);
303         compare_with_data_out(fname, buf, buf_offset);
304         st = load_object_from("buffer", buf, buf_offset, AS_PER, 0);
305         assert(st);
306
307         save_object_as(st, AS_XER);
308         fprintf(stderr, "=== original ===\n");
309         fwrite(fbuf, 1, size, stderr);
310         fprintf(stderr, "=== re-encoded ===\n");
311         fwrite(buf, 1, buf_offset, stderr);
312         fprintf(stderr, "=== end ===\n");
313
314         if(fname[strlen(fname) - 4] == 'X')
315                 assert(!xer_encoding_equal((char *)fbuf, size, (char *)buf, buf_offset));
316         else
317                 assert(xer_encoding_equal((char *)fbuf, size, (char *)buf, buf_offset));
318
319         ASN_STRUCT_FREE(asn_DEF_PDU, st);
320 }
321
322 /*
323  * Decode the .der files and try to regenerate them.
324  */
325 static int
326 process(const char *fname) {
327         unsigned char fbuf[sizeof(SRCDIR_S) + 4096];
328         char *ext = strrchr(fname, '.');
329         int rd;
330         FILE *fp;
331
332         if(ext == 0 || strcmp(ext, ".in"))
333                 return 0;
334
335         fprintf(stderr, "\nProcessing file [../%s]\n", fname);
336
337         snprintf((char *)fbuf, sizeof(fbuf), SRCDIR_S "/data-126/%s", fname);
338         fp = fopen((char *)fbuf, "r");
339         assert(fp);
340
341         rd = fread(fbuf, 1, sizeof(fbuf), fp);
342         fclose(fp);
343
344         assert((size_t)rd < sizeof(fbuf));      /* expect small files */
345
346         process_XER_data(fname, fbuf, rd);
347
348         fprintf(stderr, "Finished [%s]\n", fname);
349
350         return 1;
351 }
352
353 int
354 main() {
355         DIR *dir;
356         struct dirent *dent;
357         int processed_files = 0;
358         char *str;
359
360         /* Process a specific test file */
361         str = getenv("DATA_126_FILE");
362         if(str && strncmp(str, "data-126-", 9) == 0) {
363                 process(str);
364                 return 0;
365         }
366
367         dir = opendir(SRCDIR_S "/data-126");
368         assert(dir);
369
370         /*
371          * Process each file in that directory.
372          */
373         while((dent = readdir(dir))) {
374                 if(strncmp(dent->d_name, "data-126-", 9) == 0)
375                         if(process(dent->d_name))
376                                 processed_files++;
377         }
378
379         assert(processed_files);
380         closedir(dir);
381
382         return 0;
383 }
384