/** @file testio.c @short Test program for eventio data format. @author Konrad Bernloehr @date 1994, 1997, 2000 @date CVS $Date: 2002-07-25 17:57:05 $ @version CVS $Revision: 1.1 $ */ /* Copyright (C) 1994, 1997, 2000 Konrad Bernloehr. All rights reserved. */ #include "initial.h" #include "warning.h" #include "io_basic.h" struct test_struct { long lvar[2]; int ilvar[2]; int isvar[2]; short svar[3]; double fvar[2]; double dvar[2]; int8_t i8var[2]; uint8_t u8var[2]; int16_t i16var[2]; uint16_t u16var[2]; int32_t i32var[2]; uint32_t u32var[2]; #ifdef HAVE_64BIT_INT int64_t i64var[2]; uint64_t u64var[2]; #endif }; typedef struct test_struct TEST_DATA; static int care_long, care_int, care_short; int datacmp ARGLIST((TEST_DATA *data1, TEST_DATA *data2)); int write_test1 ARGLIST((TEST_DATA *data, IO_BUFFER *iobuf)); int read_test1 ARGLIST((TEST_DATA *data, IO_BUFFER *iobuf)); int write_test2 ARGLIST((TEST_DATA *data, IO_BUFFER *iobuf)); int read_test2 ARGLIST((TEST_DATA *data, IO_BUFFER *iiobuf)); /* ------------------------ datacmp ---------------------- */ /** * @short Compare elements of test data structures. * Compare elements of test data structures with the accuracy * relevant to the I/O package. * * @param data1 first data structure * @param data2 second data structure * * @return 0 (something did not match), 1 (O.K.) * */ int datacmp(data1,data2) TEST_DATA *data1; TEST_DATA *data2; { int i, ok; ok = 1; for (i=0; i<2; i++) if ( (int32_t)data1->lvar[i] != (int32_t)data2->lvar[i] ) { fprintf(stderr,"Long variable %d does not match: %08lx <--> %08lx\n", i+1,data1->lvar[i],data2->lvar[i]); ok = 0; } else if ( data1->lvar[i] != data2->lvar[i] ) care_long = 1; for (i=0; i<2; i++) if ( (int32_t)data1->ilvar[i] != (int32_t)data2->ilvar[i] ) { fprintf(stderr,"Int 'l' variable %d does not match: %08x <--> %08x\n", i+1,data1->ilvar[i],data2->ilvar[i]); ok = 0; } for (i=0; i<2; i++) if ( (int16_t)data1->isvar[i] != (int16_t)data2->isvar[i] ) { fprintf(stderr,"Int 's' variable %d does not match: %04x <--> %04x\n", i+1,data1->isvar[i],data2->isvar[i]); ok = 0; } else if ( data1->isvar[i] != data2->isvar[i] ) care_short = 1; for (i=0; i<3; i++) if ( data1->svar[i] != data2->svar[i] ) { fprintf(stderr,"Short variable %d does not match: %04x <--> %04x\n", i+1,data1->svar[i],data2->svar[i]); ok = 0; } for (i=0; i<2; i++) { float f1, f2; f1 = (float) data1->fvar[i]; f2 = (float) data2->fvar[i]; if ( f1 != f2 ) { fprintf(stderr,"Float variable %d does not match: %08x <--> %08x\n", i+1,*((int *)(&f1)),*((int *)(&f2))); ok = 0; } } for (i=0; i<2; i++) if ( data1->dvar[i] != data2->dvar[i] ) { double f1, f2; f1 = data1->dvar[i]; f2 = data2->dvar[i]; fprintf(stderr, "Double variable %d does not match: %08x%08x <--> %08x%08x\n", i+1,*((int *)(&f1)),*((int *)((char *)(&f1)+4)), *((int *)(&f2)),*((int *)((char *)(&f2)+4))); ok = 0; } for (i=0; i<2; i++) if ( data1->i8var[i] != data2->i8var[i] ) { fprintf(stderr,"Int8 variable %d does not match: %08x <--> %08x\n", i+1,data1->i8var[i],data2->i8var[i]); ok = 0; } for (i=0; i<2; i++) if ( data1->u8var[i] != data2->u8var[i] ) { fprintf(stderr,"UInt8 variable %d does not match: %08x <--> %08x\n", i+1,data1->u8var[i],data2->u8var[i]); ok = 0; } for (i=0; i<2; i++) if ( data1->i16var[i] != data2->i16var[i] ) { fprintf(stderr,"Int16 variable %d does not match: %08x <--> %08x\n", i+1,data1->i16var[i],data2->i16var[i]); ok = 0; } for (i=0; i<2; i++) if ( data1->u16var[i] != data2->u16var[i] ) { fprintf(stderr,"UInt16 variable %d does not match: %08x <--> %08x\n", i+1,data1->u16var[i],data2->u16var[i]); ok = 0; } for (i=0; i<2; i++) if ( data1->i32var[i] != data2->i32var[i] ) { fprintf(stderr,"Int32 variable %d does not match: %08x <--> %08x\n", i+1,data1->i32var[i],data2->i32var[i]); ok = 0; } for (i=0; i<2; i++) if ( data1->u32var[i] != data2->u32var[i] ) { fprintf(stderr,"UInt32 variable %d does not match: %08x <--> %08x\n", i+1,data1->u32var[i],data2->u32var[i]); ok = 0; } #ifdef HAVE_64BIT_INT for (i=0; i<2; i++) if ( data1->i64var[i] != data2->i64var[i] ) { #ifdef SIXTY_FOUR_BITS fprintf(stderr,"Int64 variable %d does not match: %016lx <--> %016lx\n", i+1,data1->i64var[i],data2->i64var[i]); #else fprintf(stderr,"Int64 variable %d does not match: %016llx <--> %016llx\n", i+1,data1->i64var[i],data2->i64var[i]); #endif ok = 0; } for (i=0; i<2; i++) if ( data1->u64var[i] != data2->u64var[i] ) { #ifdef SIXTY_FOUR_BITS fprintf(stderr,"UInt64 variable %d does not match: %016lx <--> %016lx\n", i+1,data1->u64var[i],data2->u64var[i]); #else fprintf(stderr,"UInt64 variable %d does not match: %016llx <--> %016llx\n", i+1,data1->u64var[i],data2->u64var[i]); #endif ok = 0; } #endif return ok; } /* --------------------- write_test1 ---------------------- */ /** * @short Write test data with single-element functions * * @param data Pointer to test data structure * @param iobuf Pointer to I/O buffer * * @return 0 (O.K.), <0 (error as for put_item_end()) * */ int write_test1(data,iobuf) TEST_DATA *data; IO_BUFFER *iobuf; { IO_ITEM_HEADER item_header; item_header.type = 99; /* test data */ item_header.version = 0; /* Version 0 (test) */ item_header.ident = 123; put_item_begin(iobuf,&item_header); put_long(data->lvar[0],iobuf); put_long(data->lvar[1],iobuf); put_long((long)data->ilvar[0],iobuf); put_long((long)data->ilvar[1],iobuf); put_short(data->isvar[0],iobuf); put_short(data->isvar[1],iobuf); put_short(data->svar[0],iobuf); put_short(data->svar[1],iobuf); put_short(data->svar[2],iobuf); put_real(data->fvar[0],iobuf); put_real(data->fvar[1],iobuf); put_double(data->dvar[0],iobuf); put_double(data->dvar[1],iobuf); put_byte(data->i8var[0],iobuf); put_byte(data->i8var[1],iobuf); put_byte(data->u8var[0],iobuf); put_byte(data->u8var[1],iobuf); put_short(data->i16var[0],iobuf); put_short(data->i16var[1],iobuf); put_short(data->u16var[0],iobuf); put_short(data->u16var[1],iobuf); put_int32(data->i32var[0],iobuf); put_int32(data->i32var[1],iobuf); put_uint32(data->u32var[0],iobuf); put_uint32(data->u32var[1],iobuf); #ifdef HAVE_64BIT_INT put_vector_of_int64(&data->i64var[0],1,iobuf); put_vector_of_int64(&data->i64var[1],1,iobuf); put_vector_of_uint64(&data->u64var[0],1,iobuf); put_vector_of_uint64(&data->u64var[1],1,iobuf); #endif return(put_item_end(iobuf,&item_header)); } /* ---------------------- read_test1 ---------------------- */ /** * @short Read test data with single-element functions * * @param data Pointer to test data structure * @param iobuf Pointer to I/O buffer * * @return 0 (ok), <0 (error as for get_item_end()) * */ int read_test1(data,iobuf) TEST_DATA *data; IO_BUFFER *iobuf; { IO_ITEM_HEADER item_header; item_header.type = 99; /* test data */ if ( get_item_begin(iobuf,&item_header) < 0 ) { Warning("Missing or invalid test data block."); return -4; } data->lvar[0] = get_long(iobuf); data->lvar[1] = get_long(iobuf); data->ilvar[0] = get_long(iobuf); data->ilvar[1] = get_long(iobuf); data->isvar[0] = get_short(iobuf); data->isvar[1] = get_short(iobuf); data->svar[0] = get_short(iobuf); data->svar[1] = get_short(iobuf); data->svar[2] = get_short(iobuf); data->fvar[0] = get_real(iobuf); data->fvar[1] = get_real(iobuf); data->dvar[0] = get_double(iobuf); data->dvar[1] = get_double(iobuf); data->i8var[0] = get_byte(iobuf); data->i8var[1] = get_byte(iobuf); data->u8var[0] = get_byte(iobuf); data->u8var[1] = get_byte(iobuf); data->i16var[0] = get_short(iobuf); data->i16var[1] = get_short(iobuf); data->u16var[0] = get_short(iobuf); data->u16var[1] = get_short(iobuf); data->i32var[0] = get_int32(iobuf); data->i32var[1] = get_int32(iobuf); data->u32var[0] = get_uint32(iobuf); data->u32var[1] = get_uint32(iobuf); #ifdef HAVE_64BIT_INT get_vector_of_int64(&data->i64var[0],1,iobuf); get_vector_of_int64(&data->i64var[1],1,iobuf); get_vector_of_uint64(&data->u64var[0],1,iobuf); get_vector_of_uint64(&data->u64var[1],1,iobuf); #endif return(get_item_end(iobuf,&item_header)); } /* --------------------- write_test2 ---------------------- */ /** * @short Write test data with vector functions as far as possible * * @param data Pointer to test data structure * @param iobuf Pointer to I/O buffer * * @return 0 (ok), <0 (error as for put_item_end()) * */ int write_test2(data,iobuf) TEST_DATA *data; IO_BUFFER *iobuf; { IO_ITEM_HEADER item_header; item_header.type = 99; /* test data */ item_header.version = 0; /* Version 0 (test) */ item_header.ident = 123; put_item_begin(iobuf,&item_header); put_vector_of_long(data->lvar,2,iobuf); put_long((long)data->ilvar[0],iobuf); put_long((long)data->ilvar[1],iobuf); put_vector_of_int(data->isvar,2,iobuf); put_vector_of_short(data->svar,3,iobuf); put_vector_of_real(data->fvar,2,iobuf); put_vector_of_double(data->dvar,2,iobuf); put_vector_of_byte((uint8_t *)data->i8var,2,iobuf); put_vector_of_byte(data->u8var,2,iobuf); put_vector_of_short(data->i16var,2,iobuf); put_vector_of_short((int16_t *)data->u16var,2,iobuf); put_vector_of_int32(data->i32var,2,iobuf); put_vector_of_uint32(data->u32var,2,iobuf); #ifdef HAVE_64BIT_INT put_vector_of_int64(data->i64var,2,iobuf); put_vector_of_uint64(data->u64var,2,iobuf); #endif return(put_item_end(iobuf,&item_header)); } /* ---------------------- read_test2 ---------------------- */ /** * @short Read test data with vector functions as far as possible * * @param data Pointer to test data structure * @param iobuf Pointer to I/O buffer * * @return 0 (ok), <0 (error as for get_item_end()) * */ int read_test2(data,iobuf) TEST_DATA *data; IO_BUFFER *iobuf; { IO_ITEM_HEADER item_header; item_header.type = 99; /* test data */ if ( get_item_begin(iobuf,&item_header) < 0 ) { Warning("Missing or invalid test data block."); return -4; } get_vector_of_long(data->lvar,2,iobuf); data->ilvar[0] = get_long(iobuf); data->ilvar[1] = get_long(iobuf); get_vector_of_int(data->isvar,2,iobuf); get_vector_of_short(data->svar,3,iobuf); get_vector_of_real(data->fvar,2,iobuf); get_vector_of_double(data->dvar,2,iobuf); get_vector_of_byte((uint8_t *)data->i8var,2,iobuf); get_vector_of_byte(data->u8var,2,iobuf); get_vector_of_short(data->i16var,2,iobuf); get_vector_of_short((int16_t *)data->u16var,2,iobuf); get_vector_of_int32(data->i32var,2,iobuf); get_vector_of_uint32(data->u32var,2,iobuf); #ifdef HAVE_64BIT_INT get_vector_of_int64(data->i64var,2,iobuf); get_vector_of_uint64(data->u64var,2,iobuf); #endif return(get_item_end(iobuf,&item_header)); } /* ---------------------- perror ------------------------- */ /** * @short Replacement for function missing on OS-9 */ #ifdef OS_OS9 int perror(text) char *text; { fprintf(stderr,"%s: Error\n",text); return 0; } #endif /* ------------------------ main ------------------------- */ /** * @short Main function for I/O test program. * First writes a test data structure with the vector * functions, then the same data structure with the * single-element functions. The output file is then * closed and reopened for reading. The first structure * is then read with the single-element functions and * the second with the vector functions (i.e. the other * way as done for writing). * The data from the file is compared with the original * data, taking the relevant accuracy into account. * Note that if an 'int' variable is written via 'put_short()' * and then read again via 'get_short()' not only the * upper two bytes (on a 32-bit machine) are lost but * also the sign bit is propagated from bit 15 to the * upper 16 bits. Similarly, if a 'long' variable is written * via 'put_long()' and later read via 'get_long()' on a * 64-bit-machine, not only the upper 4 bytes are lost but * also the sign in bit 31 is propagated to the upper 32 bits. */ #ifdef ANSI_C int main (int argc, char **argv) #else int main (argc, argv) int argc; char **argv; #endif { IO_BUFFER *iobuf; IO_ITEM_HEADER item_header; FILE *output = NULL, *input; TEST_DATA tdata, cdata1, cdata2; int ok; tdata.lvar[0] = 0x01020304L; tdata.lvar[1] = 0xf1f2f3f4L; tdata.ilvar[0] = 0x01020304; tdata.ilvar[1] = 0xf1f2f3f4; tdata.isvar[0] = 0x0102; tdata.isvar[1] = 0xf1f2; tdata.svar[0] = 0x0102; tdata.svar[1] = (short) 0xf1f2; tdata.svar[2] = 0x0a0b; tdata.fvar[0] = 2.38793926059e-38; tdata.fvar[1] = -2.40608939547e+30; tdata.dvar[0] = 2.38793926059674673672e-140; tdata.dvar[1] = -2.40608939547354636548e+180; tdata.i8var[0] = 0x1e; tdata.i8var[1] = 0xe1; tdata.u8var[0] = 0x1e; tdata.u8var[1] = 0xe1; tdata.i16var[0] = 0x1e2e; tdata.i16var[1] = 0xe2e1; tdata.u16var[0] = 0x1e2e; tdata.u16var[1] = 0xe2e1; tdata.i32var[0] = 0x1e2e3e4e; tdata.i32var[1] = 0xe4e3e2e1; tdata.u32var[0] = 0x1e2e3e4e; tdata.u32var[1] = 0xe4e3e2e1; #ifdef HAVE_64BIT_INT tdata.i64var[0] = 0x1a2a3a4a5a6a7a8a; tdata.i64var[1] = 0xa8a7a6a5a4a3a2a1; tdata.u64var[0] = 0x1b2b3b4b5b6b7b8b; tdata.u64var[1] = 0xb8b7b6b5b4b3b2b1; #endif if ( (iobuf = allocate_io_buffer((size_t)1000)) == (IO_BUFFER *) NULL ) exit(1); if ( argc > 1 ) { if ( (output = fopen(argv[1],WRITE_BINARY)) == (FILE *) NULL ) { perror(argv[1]); exit(1); } iobuf->output_file = output; } else { fprintf(stderr,"Syntax: %s filename\n",argv[0]); exit(1); } fprintf(stderr,"\nWrite test data to file '%s'.\n",argv[1]); fprintf(stderr,"Default byte order, using mainly vector functions.\n"); write_test2(&tdata,iobuf); fprintf(stderr,"Default byte order, using single-element functions.\n"); write_test1(&tdata,iobuf); iobuf->byte_order = 1; fprintf(stderr,"Reversed byte order, using single-element functions.\n"); write_test1(&tdata,iobuf); iobuf->byte_order = 0; fprintf(stderr,"Normal byte order, using single-element functions.\n"); write_test1(&tdata,iobuf); fprintf(stderr,"Write tests done.\n\n"); fclose(output); iobuf->output_file = output = NULL; if ( (input = fopen(argv[1],READ_BINARY)) == (FILE *) NULL ) { perror(argv[1]); exit(1); } iobuf->input_file = input; ok = 1; fprintf(stderr,"Read test data from file '%s'.\n",argv[1]); fprintf(stderr,"Default byte order, using single-element functions.\n"); if ( find_io_block(iobuf,&item_header) < 0 ) { Error("*** Finding I/O block 1 failed"); exit(1); } if ( read_io_block(iobuf,&item_header) < 0 ) { Error("*** Reading I/O block 1 failed"); exit(1); } if ( read_test1(&cdata1,iobuf) < 0 ) { Error("*** Read test 1 failed"); exit(1); } if ( datacmp(&tdata,&cdata1) != 1 ) { Error("*** Data from read test 1 does not match."); ok = 0; } fprintf(stderr,"Default byte order, using mainly vector functions.\n"); if ( find_io_block(iobuf,&item_header) < 0 ) { Error("*** Finding I/O block 1 failed"); exit(1); } if ( read_io_block(iobuf,&item_header) < 0 ) { Error("*** Reading I/O block 1 failed"); exit(1); } if ( read_test2(&cdata2,iobuf) < 0 ) { Error("*** Read test 2 failed"); exit(1); } if ( datacmp(&tdata,&cdata2) != 1 ) { Error("*** Data from read test 2 does not match"); ok = 0; } fprintf(stderr,"Reversed byte order, using single-element functions.\n"); if ( find_io_block(iobuf,&item_header) < 0 ) { Error("*** Finding I/O block 3 failed"); exit(1); } if ( read_io_block(iobuf,&item_header) < 0 ) { Error("*** Reading I/O block 3 failed"); exit(1); } if ( read_test1(&cdata1,iobuf) < 0 ) { Error("*** Read test 3 failed"); exit(1); } if ( datacmp(&tdata,&cdata1) != 1 ) { Error("*** Data from read test 3 does not match."); ok = 0; } fprintf(stderr,"Normal byte order, using single-element functions.\n"); if ( find_io_block(iobuf,&item_header) < 0 ) { Error("*** Finding I/O block 4 failed"); exit(1); } if ( read_io_block(iobuf,&item_header) < 0 ) { Error("*** Reading I/O block 4 failed"); exit(1); } if ( read_test1(&cdata2,iobuf) < 0 ) { Error("*** Read test 4 failed"); exit(1); } if ( datacmp(&tdata,&cdata2) != 1 ) { Error("*** Data from read test 4 does not match"); ok = 0; } Information("Read tests done\n"); if ( ok ) Information("Everthing is ok. Congratulations!\n"); if ( care_long ) { Information("Note: on this machine you should care about the sign propagation"); Information("of 'LONG' (INT32) data elements to long integer variables.\n"); } if ( care_int ) { Information("Note: on this machine you should care about the sign propagation"); Information("of 'LONG' (INT32) data elements to 32 bit integer variables.\n"); } if ( care_short ) { Information("Note: on this machine you should care about the sign propagation"); Information("of 'SHORT' data elements to integer or long integer variables.\n"); } #ifdef HAVE_64BIT_INT Information("On this machine you can read and write 64-bit integers but you should"); Information("be aware that this feature is not available on all systems otherwise"); Information("supported by eventio."); #ifdef SIXTY_FOUR_BITS Information("These 64-bit integers are native types.\n"); #else Information("These 64-bit integers are implemented through the C compiler.\n"); #endif #else Information("On this system no 64-bit integers are supported.\n"); #endif return 0; }