NativeEnumerated.c vars NULL init and check
[com/asn1c.git] / tests / tests-c-compiler / check-src / check-62.c
1 #undef  NDEBUG
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <sys/types.h>
5 #include <unistd.h>     /* for chdir(2), getcwd(3) */
6 #include <string.h>
7 #include <dirent.h>
8 #include <assert.h>
9 #include <errno.h>
10
11 #include <T.h>
12
13 #ifndef SRCDIR
14 #define SRCDIR_S ".."
15 #else
16 #define STRINGIFY_MACRO2(x) #x
17 #define STRINGIFY_MACRO(x)  STRINGIFY_MACRO2(x)
18 #define SRCDIR_S    STRINGIFY_MACRO(SRCDIR)
19 #endif
20
21 enum expectation {
22         EXP_OK,         /* Encoding/decoding must succeed */
23         EXP_BROKEN,     /* Decoding must fail */
24         EXP_RECLESS,    /* Reconstruction is allowed to yield less data */
25         EXP_DIFFERENT,  /* Reconstruction will yield different encoding */
26 };
27
28 static unsigned char buf[4096];
29 static int buf_offset;
30
31 static int
32 _buf_writer(const void *buffer, size_t size, void *app_key) {
33         unsigned char *b, *bend;
34         (void)app_key;
35         assert(buf_offset + size < sizeof(buf));
36         if (buffer) {
37                 memcpy(buf + buf_offset, buffer, size);
38         }
39         b = buf + buf_offset;
40         bend = b + size;
41         printf("=> [");
42         for(; b < bend; b++)
43                 printf(" %02X", *b);
44         printf("]:%zd\n", size);
45         buf_offset += size;
46         return 0;
47 }
48
49 static int
50 save_object(T_t *st) {
51         asn_enc_rval_t rval; /* Return value */
52
53         buf_offset = 0;
54         
55         rval = der_encode(&asn_DEF_T, st, _buf_writer, 0);
56         if (rval.encoded == -1) {
57                 fprintf(stderr,
58                         "Cannot encode %s: %s\n",
59                         rval.failed_type->name, strerror(errno));
60                 assert(rval.encoded != -1);
61                 return -1;      /* JIC */
62         }
63
64         fprintf(stderr, "SAVED OBJECT IN SIZE %d\n", buf_offset);
65
66         return 0;
67 }
68
69 static T_t *
70 load_object(enum expectation expectation, unsigned char *fbuf, size_t size) {
71         asn_dec_rval_t rval;
72         T_t *st = 0;
73         int csize;
74
75         fprintf(stderr, "LOADING OBJECT OF SIZE %d\n", (int)size);
76
77         /* Perform multiple iterations with multiple chunks sizes */
78         for(csize = 1; csize < 20; csize += 1) {
79                 int fbuf_offset = 0;
80                 int fbuf_left = size;
81                 int fbuf_chunk = csize;
82
83                 if(st) ASN_STRUCT_FREE(asn_DEF_T, st);
84                 st = 0;
85
86                 do {
87                         fprintf(stderr, "Decoding from %d with %d (left %d)\n",
88                                 fbuf_offset, fbuf_chunk, fbuf_left);
89                         rval = ber_decode(0, &asn_DEF_T, (void **)&st,
90                                 fbuf + fbuf_offset,
91                                         fbuf_chunk < fbuf_left 
92                                                 ? fbuf_chunk : fbuf_left);
93                         fbuf_offset += rval.consumed;
94                         fbuf_left -= rval.consumed;
95                         if(rval.code == RC_WMORE)
96                                 fbuf_chunk += 1;        /* Give little more */
97                         else
98                                 fbuf_chunk = csize;     /* Back off */
99                 } while(fbuf_left && rval.code == RC_WMORE);
100
101                 if(expectation != EXP_BROKEN) {
102                         assert(rval.code == RC_OK);
103                         assert(fbuf_offset == (ssize_t)size);
104                 } else {
105                         assert(rval.code != RC_OK);
106                         fprintf(stderr, "Failed, but this was expected\n");
107                         ASN_STRUCT_FREE(asn_DEF_T, st);
108                         st = 0; /* ignore leak for now */
109                 }
110         }
111
112         if(st) asn_fprint(stderr, &asn_DEF_T, st);
113         return st;
114 }
115
116
117 static void
118 process_data(enum expectation expectation, unsigned char *fbuf, ssize_t size) {
119         T_t *st;
120         int ret;
121
122         st = load_object(expectation, fbuf, size);
123         if(!st) return;
124
125         ret = save_object(st);
126         assert(buf_offset < (ssize_t)sizeof(buf));
127         assert(ret == 0);
128
129         switch(expectation) {
130         case EXP_RECLESS:
131                 assert(buf_offset > 0 && buf_offset < size);
132                 assert(memcmp(buf + 2, fbuf + 2, buf_offset - 2) == 0);
133                 break;
134         case EXP_DIFFERENT:
135                 assert(buf_offset > 0 && buf_offset < size);
136                 break;
137         case EXP_BROKEN:
138                 assert(buf_offset != size
139                         || memcmp(buf, fbuf, buf_offset));
140                 break;
141         case EXP_OK:
142                 assert(buf_offset == (ssize_t)size);
143                 assert(memcmp(buf, fbuf, buf_offset) == 0);
144                 break;
145         }
146
147         ASN_STRUCT_FREE(asn_DEF_T, st);
148 }
149
150 /*
151  * Decode the .der files and try to regenerate them.
152  */
153 static int
154 process(const char *fname) {
155         char prevdir[256];
156         unsigned char fbuf[4096];
157         char *ext = strrchr(fname, '.');
158         enum expectation expectation;
159         char *cwd;
160         int ret;
161         int rd;
162         FILE *fp;
163
164         if(ext == 0 || strcmp(ext, ".ber"))
165                 return 0;
166
167         switch(ext[-1]) {
168         case 'B':       /* The file is intentionally broken */
169                 expectation = EXP_BROKEN; break;
170         case 'D':       /* Reconstructing should yield different data */
171                 expectation = EXP_DIFFERENT; break;
172         case 'L':       /* Extensions are present */
173                 expectation = EXP_RECLESS; break;
174         default:
175                 expectation = EXP_OK; break;
176         }
177
178         fprintf(stderr, "\nProcessing file [../%s]\n", fname);
179
180         cwd = getcwd(prevdir, sizeof(prevdir));
181         assert(cwd != NULL);
182         ret = chdir(SRCDIR_S "/data-62");
183         assert(ret == 0);
184         fp = fopen(fname, "r");
185         ret = chdir(prevdir);
186         assert(ret == 0);
187         assert(fp);
188
189         rd = fread(fbuf, 1, sizeof(fbuf), fp);
190         fclose(fp);
191
192         assert(rd < (ssize_t)sizeof(fbuf));     /* expect small files */
193
194         process_data(expectation, fbuf, rd);
195
196         return 1;
197 }
198
199 int
200 main() {
201         DIR *dir;
202         struct dirent *dent;
203         int processed_files = 0;
204         char *str;
205
206         dir = opendir(SRCDIR_S "/data-62");
207         assert(dir);
208
209         str = getenv("DATA_62_FILE");
210         if(str && strncmp(str, "data-62-", 8) == 0)
211                 process(str);
212
213         while((dent = readdir(dir))) {
214                 if(strncmp(dent->d_name, "data-62-", 8) == 0)
215                         if(process(dent->d_name))
216                                 processed_files++;
217         }
218
219         assert(processed_files);
220         closedir(dir);
221
222         return 0;
223 }
224