1 
2 #include "config.h"
3 #include <fcntl.h>
4 #ifdef STDC_HEADERS
5 #include <stdlib.h>
6 #endif
7 #include <stdio.h>
8 #ifdef HAVE_UNISTD_H
9 #include <unistd.h>
10 #endif
11 #ifdef HAVE_MEMORY_H
12 #include <memory.h>
13 #endif
14 #ifdef HAVE_MALLOC_H
15 #include <malloc.h>
16 #endif
17 #include <string.h>
18 #include <assert.h>
19 #include "ffs.h"
20 
21 #include "test_funcs.h"
22 
23 static void test_receive(char *buffer, int buf_size, int finished,
24 			       int test_level);
25 static void test_all_receive(char *buffer, int buf_size, int finished);
26 static void write_buffer(char *buf, int size);
27 static void read_test_only();
28 
29 static int write_output = 0;
30 static char *output_file = NULL;
31 static char *read_file = NULL;
32 static int fail = 0;
33 static char *test_only = NULL;
34 
35 static FFSContext rcv_context = NULL;
36 static int verbose = 0;
37 static FMContext loaded_FMcontext = NULL;
38 
39 int
main(argc,argv)40 main(argc, argv)
41 int argc;
42 char **argv;
43 {
44     FMContext src_context;
45     FFSBuffer encode_buffer;
46     char *xfer_buffer;
47     int buf_size;
48     int i;
49     struct node nodes[10];
50     struct visit_table v;
51     FMFormat node_ioformat, psa_ioformat, reader_register_ioformat;
52 
53     init_written_data();
54 
55     for (i=1; i<argc; i++) {
56 	if (strcmp(argv[i], "-w") == 0) {
57 	    output_file = argv[++i];
58 	    write_output++;
59 	} else if (strcmp(argv[i], "-r") == 0) {
60 	    read_file = argv[++i];
61 	} else if (strcmp(argv[i], "-v") == 0) {
62 	    verbose++;
63 	} else if (strcmp(argv[i], "-t") == 0) {
64 	    test_only = argv[++i];
65 	} else {
66 	    printf("Unknown argument %s\n", argv[i]);
67 	    printf("Usage:\n\t-w\t  write test output\n");
68 	    printf("\t-r file\t  rest/process test data in <file>\n");
69 	    printf("\t-t test\t  test only format <test>\n");
70 	    exit(1);
71 	}
72     }
73 
74     if (read_file) {
75 	read_test_only();
76 	free_written_data();
77 	if (rcv_context != NULL) {
78 	    free_FFSContext(rcv_context);
79 	    rcv_context = NULL;
80 	}
81 	if (loaded_FMcontext) {
82 	    free_FMcontext(loaded_FMcontext);
83 	}
84 	if (fail) exit(1);
85 	exit(0);
86     }
87     src_context = create_FMcontext();
88     encode_buffer = create_FFSBuffer();
89 
90     node_ioformat = register_data_format(src_context, node_format_list);
91     psa_ioformat = register_data_format(src_context, pointer_to_static_format_list);
92     reader_register_ioformat = register_data_format(src_context, reader_register_format_list);
93 
94     for (i = 0; i < sizeof(nodes)/sizeof(nodes[0]); i++) {
95 	nodes[i].node_num = i;
96 	nodes[i].link1 = nodes[i].link2 = NULL;
97     }
98 
99     for (i=0; i <  sizeof(nodes)/sizeof(nodes[0]) - 1; i++) {
100 	nodes[i].link1 = &nodes[i+1];
101     }
102 /*    nodes[0].link2 = &nodes[sizeof(nodes)/sizeof(nodes[0])-1];*/
103     v.node_count = 0;
104     nodes[0].node_num = calc_signature(&nodes[0], &v);
105     xfer_buffer = FFSencode(encode_buffer, node_ioformat,
106 					  &nodes[0], &buf_size);
107     test_all_receive(xfer_buffer, buf_size, 0);
108     write_buffer(xfer_buffer, buf_size);
109 
110     nodes[0].link2 = NULL;
111     nodes[sizeof(nodes)/sizeof(nodes[0]) - 1].link1 = &nodes[2];
112     v.node_count = 0;
113     nodes[0].node_num = 0;
114     nodes[0].node_num = calc_signature(&nodes[0], &v);
115     xfer_buffer = FFSencode(encode_buffer, node_ioformat,
116 					  &nodes[0], &buf_size);
117     test_all_receive(xfer_buffer, buf_size, 0);
118     write_buffer(xfer_buffer, buf_size);
119 
120     for (i=0; i <  sizeof(nodes)/sizeof(nodes[0]) - 1; i++) {
121 	nodes[i].link1 = nodes[i].link2 = NULL;
122     }
123     nodes[0].link1 = &nodes[1];
124     nodes[0].link2 = &nodes[2];
125     nodes[1].link1 = &nodes[3];
126     nodes[1].link2 = &nodes[4];
127     nodes[2].link1 = &nodes[5];
128     nodes[2].link2 = &nodes[6];
129     nodes[3].link1 = &nodes[7];
130     nodes[3].link2 = &nodes[8];
131     nodes[4].link1 = &nodes[9];
132 
133     v.node_count = 0;
134     nodes[0].node_num = 0;
135     nodes[0].node_num = calc_signature(&nodes[0], &v);
136     xfer_buffer = FFSencode(encode_buffer, node_ioformat,
137 					  &nodes[0], &buf_size);
138     test_all_receive(xfer_buffer, buf_size, 0);
139     write_buffer(xfer_buffer, buf_size);
140 
141     xfer_buffer = FFSencode(encode_buffer, psa_ioformat,
142 					  &psa, &buf_size);
143     test_all_receive(xfer_buffer, buf_size, 0);
144     write_buffer(xfer_buffer, buf_size);
145 
146     xfer_buffer = FFSencode(encode_buffer, reader_register_ioformat,
147 					  &reader_register, &buf_size);
148     test_all_receive(xfer_buffer, buf_size, 0);
149     write_buffer(xfer_buffer, buf_size);
150 
151 
152     free_FMcontext(src_context);
153     free_FFSBuffer(encode_buffer);
154     src_context = NULL;
155     test_all_receive(NULL, 0, 1);
156     write_buffer(NULL, 0);
157 
158     free_written_data();
159     if (rcv_context != NULL) {
160 	free_FFSContext(rcv_context);
161 	rcv_context = NULL;
162     }
163     if (loaded_FMcontext) {
164 	free_FMcontext(loaded_FMcontext);
165     }
166     if (fail) exit(1);
167     return 0;
168 }
169 
170 /* NT needs O_BINARY, but it doesn't exist elsewhere */
171 #ifndef O_BINARY
172 #define O_BINARY 0
173 #endif
174 
175 static char *
get_buffer(size_p)176 get_buffer(size_p)
177 int *size_p;
178 {
179     static int file_fd = 0;
180     static char *buffer = NULL;
181     char *tmp_buffer;
182     static int last_size = -1;
183     unsigned short ssize;
184     int to_read;
185     int tmp_size;
186     unsigned char csize;
187     unsigned int beef = 0xdeadbeef;
188 
189     if (read_file == NULL) exit(1);
190 
191     if (loaded_FMcontext == NULL) {
192 	loaded_FMcontext = create_local_FMcontext();
193     }
194     if (file_fd == 0) {
195 	file_fd = open(read_file, O_RDONLY|O_BINARY, 0777);
196 	buffer = malloc(1);
197     }
198     if (last_size != -1) {
199 	if (memcmp(buffer+last_size, &beef, 4) != 0) {
200 	    printf("memory overwrite error\n");
201 	}
202     }
203     if (read(file_fd, &csize, 1) != 1) exit(1);	/* low byte of 2-byte size */
204     ssize = csize;
205     if (read(file_fd, &csize, 1) != 1) exit(1);	/* high byte of 2-byte size */
206     ssize += ((csize << 8) & 0xff00);
207     to_read = ssize;
208     buffer = realloc(buffer, to_read+4);
209     tmp_buffer = buffer;
210     while((tmp_size = read(file_fd, tmp_buffer, to_read)) != to_read) {
211 	if (tmp_size == 0) {
212 	    free(buffer);
213 	    return NULL;
214 	} else if (tmp_size == -1) {
215 	    perror("Read failure");
216 	    free(buffer);
217 	    return NULL;
218 	}
219 	to_read -= tmp_size;
220 	tmp_buffer += tmp_size;
221     }
222     last_size = ssize;
223     memcpy(buffer+last_size, &beef, 4);
224     if (ssize == 0) {
225 	free(buffer);
226 	close(file_fd);
227 	file_fd = 0;
228 	return NULL;
229     } else {
230 	*size_p = ssize;
231 	return buffer;
232     }
233 }
234 
235 static void
read_test_only()236 read_test_only()
237 {
238     char *input;
239     int size;
240     while ((input = get_buffer(&size)) != NULL) {
241 	test_all_receive(input, size, 0);
242     }
243     test_all_receive(NULL, 0, 1);
244     free(input);
245     if (rcv_context != NULL) {
246 	free_FFSContext(rcv_context);
247 	rcv_context = NULL;
248     }
249 }
250 
251 static FFSTypeHandle node_ioformat;
252 static FFSTypeHandle psa_ioformat;
253 static FFSTypeHandle reader_register_ioformat;
254 
255 static void
set_targets(context)256 set_targets(context)
257 FFSContext context;
258 {
259     node_ioformat = FFSset_fixed_target(context, node_format_list);
260     psa_ioformat = FFSset_fixed_target(context, pointer_to_static_format_list);
261     reader_register_ioformat = FFSset_fixed_target(context, reader_register_format_list);
262 }
263 
base_size_func(FFSContext context,char * src,int rec_len,int native_struct_size)264 int base_size_func(FFSContext context, char *src, int rec_len,
265 		   int native_struct_size)
266 {
267     return native_struct_size;
268 }
269 
total_size_func(FFSContext context,char * src,int rec_len,int native_struct_size)270 int total_size_func(FFSContext context, char *src, int rec_len,
271 		    int native_struct_size)
272 {
273     return FFS_est_decode_length(context, src, rec_len);
274 }
275 
276 static int
decode_in_place(FFSContext context,char * src,int src_len,void * dest)277 decode_in_place(FFSContext context, char *src, int src_len, void *dest)
278 {
279     if (FFSdecode_in_place_possible(FFSTypeHandle_from_encode(context, src))) {
280 	int ret, header_len;
281 	char *real_dest;
282 	ret = FFSdecode_in_place(context, src, (void**)&real_dest);
283 	header_len = real_dest - src;
284 	memcpy(dest, real_dest, src_len - header_len);
285 	return ret;
286     } else {
287 	return FFSdecode_to_buffer(context, src, dest);
288     }
289 }
290 
291 static int
decode_IOcontext_wrapper(FFSContext context,char * src,int src_len,void * dest)292 decode_IOcontext_wrapper(FFSContext context, char *src, int src_len, void *dest)
293 {
294     return FFSdecode(context, src, dest);
295 }
296 
297 static int
decode_to_buffer_IOcontext_wrapper(FFSContext context,char * src,int src_len,void * dest)298 decode_to_buffer_IOcontext_wrapper(FFSContext context, char *src, int src_len,
299 				   void *dest)
300 {
301     return FFSdecode_to_buffer(context, src, dest);
302 }
303 
304 typedef int (*size_func_t)(FFSContext context, char *src, int buf_size,
305 				   int nativ_struct);
306 
307 typedef int (*decode_func_t)(FFSContext context, char *src, int src_len,
308 				   void *dest);
309 
310 size_func_t size_funcs[] = {base_size_func, total_size_func, total_size_func};
311 decode_func_t decode_funcs[] = {decode_IOcontext_wrapper,
312 				decode_to_buffer_IOcontext_wrapper,
313 				decode_in_place};
314 
315 
316 #define NUM_TESTS 3
317 
318 static void
test_all_receive(buffer,buf_size,finished)319 test_all_receive(buffer, buf_size, finished)
320 char *buffer;
321 int buf_size;
322 int finished;
323 {
324     int test_type = 0;
325     char *tmp_buffer = malloc(buf_size);
326     for ( test_type = 0; test_type < NUM_TESTS; test_type++) {
327 	memcpy(tmp_buffer, buffer, buf_size);
328 	test_receive(tmp_buffer, buf_size, finished, test_type);
329     }
330     free(tmp_buffer);
331 }
332 
333 static void*
get_mem(size)334 get_mem(size)
335 int size;
336 {
337     char *buffer;
338     unsigned int beef = 0xdeadbeef;
339 
340     buffer = malloc(size+4);
341     memcpy(buffer+size, &beef, 4);
342     return buffer;
343 }
344 
345 static void
check_mem(size,buffer)346 check_mem(size, buffer)
347 int size;
348 char *buffer;
349 {
350     unsigned int beef = 0xdeadbeef;
351     if (memcmp(buffer+size, &beef, 4) != 0) {
352 	printf("memory overwrite error\n");
353     }
354 }
355 
356 
357 static void
test_receive(buffer,buf_size,finished,test_level)358 test_receive(buffer, buf_size, finished, test_level)
359 char *buffer;
360 int buf_size;
361 int finished;
362 int test_level;
363 {
364     static FFSContext c = NULL;
365     static int node_rec_count[NUM_TESTS] = {0,0,0};
366 
367     static int unknown_rec_count[NUM_TESTS] = {0,0,0};
368     size_func_t size_func = size_funcs[test_level];
369     decode_func_t decode_func = decode_funcs[test_level];
370     if (c == NULL) {
371 	c = create_FFSContext();
372 	rcv_context = c;
373 	set_targets(rcv_context);
374     }
375     if (!finished) {
376 /*	char *comment;*/
377 	FFSTypeHandle buffer_format = FFS_target_from_encode(rcv_context, buffer);
378 
379 	if (buffer_format == NULL) {
380 	    printf("No format!\n");
381 	    exit(1);
382 	}
383 	if (((test_only == NULL) || (strcmp(test_only, "node") == 0)) &&
384 		   (buffer_format == node_ioformat)) {
385 	    int size = size_func(rcv_context, buffer, buf_size,
386 				 sizeof(add_rec));
387 	    node_ptr read_data = get_mem(size);
388 	    struct visit_table v;
389 	    int signature, calculated_sig;
390 	    memset(read_data, 0, size);
391 	    if (!decode_func(rcv_context, buffer, buf_size, read_data))
392 		printf("decode failed, decode msg format\n");
393 	    signature = read_data->node_num;
394 	    read_data->node_num = 0;
395 	    v.node_count = 0;
396 	    calculated_sig = calc_signature(read_data, &v);
397 	    if (signature != calculated_sig) {
398 		printf("Node sig not right, calculated %d, expected %d\n",
399 		       calculated_sig, signature);
400 		fail++;
401 	    }
402 	    check_mem(size, (char*)read_data);
403 	    free(read_data);
404 	    node_rec_count[test_level]++;
405 	} else 	if (((test_only == NULL) || (strcmp(test_only, "psa") == 0)) &&
406 		   (buffer_format == psa_ioformat)) {
407 	    int size = size_func(rcv_context, buffer, buf_size,
408 				 sizeof(add_rec));
409 	    pointer_to_static_array_ptr read_data = get_mem(size);
410 	    memset(read_data, 0, size);
411 	    if (!decode_func(rcv_context, buffer, buf_size, read_data))
412 		printf("decode failed, pointer_to_static_array data failed\n");
413 	    if (!pointer_to_static_rec_eq(read_data, &psa)) {
414 		printf("Pointer to static array failure\n");
415 		fail++;
416 	    }
417 	    check_mem(size, (char*)read_data);
418 	    free(read_data);
419 	} else 	if (((test_only == NULL) || (strcmp(test_only, "reader_register") == 0)) &&
420 		   (buffer_format == reader_register_ioformat)) {
421 	    int size = size_func(rcv_context, buffer, buf_size,
422 				 sizeof(add_rec));
423 	    struct _reader_register_msg *read_data = get_mem(size);
424 	    memset(read_data, 0, size);
425 	    if (!decode_func(rcv_context, buffer, buf_size, read_data))
426 		printf("decode failed, pointer_to_static_array data failed\n");
427 	    if (!reader_register_rec_eq(read_data, &reader_register)) {
428 		printf("Pointer to reader_register failure\n");
429 		fail++;
430 	    }
431 	    check_mem(size, (char*)read_data);
432 	    free(read_data);
433 	} else if (test_only == NULL) {
434 	    printf("discarding a record\n");
435 	    unknown_rec_count[test_level]++;
436 	}
437     } else {
438 	/* finished */
439 	if (test_level == 0) {
440 	    free_FFSContext(rcv_context);
441 	    rcv_context = NULL;
442 	}
443 	if (test_only != NULL) return;
444 	if (node_rec_count[test_level] != 3) {
445 	    printf("Missed node, level %d\n", test_level);
446 	    fail++;
447 	}
448 	if (unknown_rec_count[test_level] != 0) {
449 	    printf("Got unknown\n");
450 	    fail++;
451 	}
452     }
453 }
454 
455 static void
write_buffer(buf,size)456 write_buffer(buf, size)
457 char *buf;
458 int size;
459 {
460     static int file_fd = 0;
461     unsigned short ssize;
462     unsigned char csize;
463     if (output_file == NULL) return;
464 
465     if (file_fd == 0) {
466 	file_fd = open(output_file, O_WRONLY|O_CREAT|O_TRUNC|O_BINARY, 0777);
467     }
468     printf("Writing buffer of size %d\n", size);
469     ssize = size;
470     csize = ssize & 0xff;
471     if (write(file_fd, &csize, 1) != 1) exit(1);/* low byte of 2-byte size */
472     csize = ((ssize >> 8) & 0xff);
473     if (write(file_fd, &csize, 1) != 1) exit(1);/* high byte of 2-byte size */
474     if (write(file_fd, buf, size) != size) exit(1);
475 }
476