blob: cdfca4b0150907f41d0fc1726d553aa5aa06b87c [file] [log] [blame]
Lev Walkina85b37d2005-02-18 10:13:44 +00001/*
2 * Mode of operation:
3 * Each of the *.in files is XER-decoded, then converted into DER,
4 * then decoded from DER and encoded into XER again. The resulting
5 * stream is compared with the corresponding .out file.
6 */
Lev Walkin3234ecc2005-02-14 17:20:23 +00007#undef NDEBUG
8#include <stdio.h>
9#include <stdlib.h>
10#include <sys/types.h>
11#include <unistd.h> /* for chdir(2) */
12#include <string.h>
13#include <dirent.h>
14#include <assert.h>
15#include <errno.h>
16
17#include <PDU.h>
18
19enum expectation {
20 EXP_OK, /* Encoding/decoding must succeed */
21 EXP_BROKEN, /* Decoding must fail */
Lev Walkin3234ecc2005-02-14 17:20:23 +000022 EXP_DIFFERENT, /* Reconstruction will yield different encoding */
23};
24
25static unsigned char buf[4096];
26static int buf_offset;
27
28static int
29_buf_writer(const void *buffer, size_t size, void *app_key) {
30 unsigned char *b, *bend;
31 (void)app_key;
32 assert(buf_offset + size < sizeof(buf));
33 memcpy(buf + buf_offset, buffer, size);
34 b = buf + buf_offset;
35 bend = b + size;
36 printf("=> [");
37 for(; b < bend; b++)
38 printf("%c", *b);
39 printf("]:%ld\n", (long)size);
40 buf_offset += size;
41 return 0;
42}
43
Lev Walkina85b37d2005-02-18 10:13:44 +000044enum der_or_xer {
45 AS_DER,
46 AS_XER,
47};
48
49static void
50save_object_as(PDU_t *st, enum der_or_xer how) {
Lev Walkin3234ecc2005-02-14 17:20:23 +000051 asn_enc_rval_t rval; /* Return value */
52
53 buf_offset = 0;
Lev Walkina85b37d2005-02-18 10:13:44 +000054
55 /*
56 * Save object using specified method.
57 */
58 switch(how) {
59 case AS_DER:
60 rval = der_encode(&asn_DEF_PDU, st,
61 _buf_writer, 0);
62 break;
63 case AS_XER:
64 rval = xer_encode(&asn_DEF_PDU, st, XER_F_BASIC,
65 _buf_writer, 0);
66 break;
67 }
Lev Walkin3234ecc2005-02-14 17:20:23 +000068 if (rval.encoded == -1) {
69 fprintf(stderr,
70 "Cannot encode %s: %s\n",
71 rval.failed_type->name, strerror(errno));
72 assert(rval.encoded != -1);
Lev Walkina85b37d2005-02-18 10:13:44 +000073 return;
Lev Walkin3234ecc2005-02-14 17:20:23 +000074 }
75
Lev Walkin3234ecc2005-02-14 17:20:23 +000076 fprintf(stderr, "SAVED OBJECT IN SIZE %d\n", buf_offset);
Lev Walkin3234ecc2005-02-14 17:20:23 +000077}
78
79static PDU_t *
Lev Walkina85b37d2005-02-18 10:13:44 +000080load_object_from(enum expectation expectation, char *fbuf, int size, enum der_or_xer how) {
Lev Walkin3234ecc2005-02-14 17:20:23 +000081 asn_dec_rval_t rval;
Lev Walkina85b37d2005-02-18 10:13:44 +000082 asn_dec_rval_t (*zer_decode)(struct asn_codec_ctx_s *,
83 asn_TYPE_descriptor_t *, void **, void *, size_t);
Lev Walkin3234ecc2005-02-14 17:20:23 +000084 PDU_t *st = 0;
85 int csize;
86
Lev Walkina85b37d2005-02-18 10:13:44 +000087 if(how == AS_DER)
88 zer_decode = ber_decode;
89 else
90 zer_decode = xer_decode;
91
92
Lev Walkin3234ecc2005-02-14 17:20:23 +000093 fprintf(stderr, "LOADING OBJECT OF SIZE %d\n", size);
94
95 /* Perform multiple iterations with multiple chunks sizes */
96 for(csize = 1; csize < 20; csize += 1) {
97 int fbuf_offset = 0;
98 int fbuf_left = size;
99 int fbuf_chunk = csize;
100
101 if(st) asn_DEF_PDU.free_struct(&asn_DEF_PDU, st, 0);
102 st = 0;
103
104 do {
105 fprintf(stderr, "Decoding from %d with %d (left %d)\n",
106 fbuf_offset, fbuf_chunk, fbuf_left);
Lev Walkina85b37d2005-02-18 10:13:44 +0000107 rval = zer_decode(0, &asn_DEF_PDU, (void **)&st,
Lev Walkin3234ecc2005-02-14 17:20:23 +0000108 fbuf + fbuf_offset,
109 fbuf_chunk < fbuf_left
Lev Walkina85b37d2005-02-18 10:13:44 +0000110 ? fbuf_chunk : fbuf_left);
Lev Walkin3234ecc2005-02-14 17:20:23 +0000111 fbuf_offset += rval.consumed;
112 fbuf_left -= rval.consumed;
113 if(rval.code == RC_WMORE)
114 fbuf_chunk += 1; /* Give little more */
115 else
116 fbuf_chunk = csize; /* Back off */
117 } while(fbuf_left && rval.code == RC_WMORE);
118
119 if(expectation != EXP_BROKEN) {
120 assert(rval.code == RC_OK);
Lev Walkina85b37d2005-02-18 10:13:44 +0000121 if(how == AS_DER) {
122 assert(fbuf_offset == size);
123 } else {
124 assert(fbuf_offset - size < 2
Lev Walkin3234ecc2005-02-14 17:20:23 +0000125 || (fbuf_offset + 1 /* "\n" */ == size
126 && fbuf[size - 1] == '\n')
127 || (fbuf_offset + 2 /* "\r\n" */ == size
128 && fbuf[size - 2] == '\r'
129 && fbuf[size - 1] == '\n')
Lev Walkina85b37d2005-02-18 10:13:44 +0000130 );
131 }
Lev Walkin3234ecc2005-02-14 17:20:23 +0000132 } else {
133 assert(rval.code != RC_OK);
134 fprintf(stderr, "Failed, but this was expected\n");
135 asn_DEF_PDU.free_struct(&asn_DEF_PDU, st, 0);
136 st = 0; /* ignore leak for now */
137 }
138 }
139
140 if(st) asn_fprint(stderr, &asn_DEF_PDU, st);
141 return st;
142}
143
Lev Walkina85b37d2005-02-18 10:13:44 +0000144static int
145xer_encoding_equal(char *obuf, size_t osize, char *nbuf, size_t nsize) {
146 char *oend = obuf + osize;
147 char *nend = nbuf + nsize;
148
149 if((osize && !nsize) || (!osize && nsize))
150 return 0; /* not equal apriori */
151
152 while(1) {
153 while(obuf < oend && isspace(*obuf)) obuf++;
154 while(nbuf < nend && isspace(*nbuf)) nbuf++;
155
156 if(obuf == oend || nbuf == nend) {
157 if(obuf == oend && nbuf == nend)
158 break;
159 fprintf(stderr, "%s data in reconstructed encoding\n",
160 (obuf == oend) ? "More" : "Less");
161 return 0;
162 }
163
164 if(*obuf != *nbuf) {
165 printf("%c%c != %c%c\n",
166 obuf[0], obuf[1],
167 nbuf[0], nbuf[1]);
168 return 0;
169 }
170 obuf++, nbuf++;
171 }
172
173 return 1;
174}
Lev Walkin3234ecc2005-02-14 17:20:23 +0000175
176static void
Lev Walkina85b37d2005-02-18 10:13:44 +0000177process_XER_data(enum expectation expectation, char *fbuf, int size) {
Lev Walkin3234ecc2005-02-14 17:20:23 +0000178 PDU_t *st;
179 int ret;
180
Lev Walkina85b37d2005-02-18 10:13:44 +0000181 st = load_object_from(expectation, fbuf, size, AS_XER);
Lev Walkin3234ecc2005-02-14 17:20:23 +0000182 if(!st) return;
183
Lev Walkina85b37d2005-02-18 10:13:44 +0000184 /* Save and re-load as DER */
185 save_object_as(st, AS_DER);
186 st = load_object_from(expectation, buf, buf_offset, AS_DER);
187 assert(st);
188
189 save_object_as(st, AS_XER);
190 fprintf(stderr, "=== original ===\n");
191 fwrite(fbuf, 1, size, stderr);
192 fprintf(stderr, "=== re-encoded ===\n");
193 fwrite(buf, 1, buf_offset, stderr);
194 fprintf(stderr, "=== end ===\n");
Lev Walkin3234ecc2005-02-14 17:20:23 +0000195
196 switch(expectation) {
Lev Walkin3234ecc2005-02-14 17:20:23 +0000197 case EXP_DIFFERENT:
Lev Walkina85b37d2005-02-18 10:13:44 +0000198 assert(!xer_encoding_equal(fbuf, size, buf, buf_offset));
Lev Walkin3234ecc2005-02-14 17:20:23 +0000199 break;
200 case EXP_BROKEN:
Lev Walkina85b37d2005-02-18 10:13:44 +0000201 assert(!xer_encoding_equal(fbuf, size, buf, buf_offset));
Lev Walkin3234ecc2005-02-14 17:20:23 +0000202 break;
203 case EXP_OK:
Lev Walkina85b37d2005-02-18 10:13:44 +0000204 assert(xer_encoding_equal(fbuf, size, buf, buf_offset));
Lev Walkin3234ecc2005-02-14 17:20:23 +0000205 break;
206 }
207
208 asn_DEF_PDU.free_struct(&asn_DEF_PDU, st, 0);
209}
210
211/*
212 * Decode the .der files and try to regenerate them.
213 */
214static int
215process(const char *fname) {
216 char fbuf[4096];
217 char *ext = strrchr(fname, '.');
218 enum expectation expectation;
219 int ret;
220 int rd;
221 FILE *fp;
222
223 if(ext == 0 || strcmp(ext, ".in"))
224 return 0;
225
226 switch(ext[-1]) {
227 case 'B': /* The file is intentionally broken */
228 expectation = EXP_BROKEN; break;
229 case 'D': /* Reconstructing should yield different data */
230 expectation = EXP_DIFFERENT; break;
Lev Walkin3234ecc2005-02-14 17:20:23 +0000231 default:
232 expectation = EXP_OK; break;
233 }
234
235 fprintf(stderr, "\nProcessing file [../%s]\n", fname);
236
237 ret = chdir("../data-70");
238 assert(ret == 0);
239 fp = fopen(fname, "r");
240 ret = chdir("../test-check-70");
241 assert(ret == 0);
242 assert(fp);
243
244 rd = fread(fbuf, 1, sizeof(fbuf), fp);
245 fclose(fp);
246
247 assert(rd < sizeof(fbuf)); /* expect small files */
248
Lev Walkina85b37d2005-02-18 10:13:44 +0000249 process_XER_data(expectation, fbuf, rd);
Lev Walkin3234ecc2005-02-14 17:20:23 +0000250
251 return 1;
252}
253
254int
255main() {
256 DIR *dir;
257 struct dirent *dent;
258 int processed_files = 0;
259 char *str;
260
Lev Walkin3234ecc2005-02-14 17:20:23 +0000261 /* Process a specific test file */
262 str = getenv("DATA_70_FILE");
263 if(str && strncmp(str, "data-70-", 8) == 0)
264 process(str);
265
Lev Walkina85b37d2005-02-18 10:13:44 +0000266 dir = opendir("../data-70");
267 assert(dir);
268
269 /*
270 * Process each file in that directory.
271 */
Lev Walkin3234ecc2005-02-14 17:20:23 +0000272 while((dent = readdir(dir))) {
273 if(strncmp(dent->d_name, "data-70-", 8) == 0)
274 if(process(dent->d_name))
275 processed_files++;
276 }
277
278 assert(processed_files);
279 closedir(dir);
280
281 return 0;
282}
283