123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399 |
- /*
- * Tests for basex.h
- *
- * Copyright (C) 2008 iptelorg GmbH
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
- /*#define NO_BASE64_LOOKUP_TABLE
- #define SINGLE_REG */
- #include "../basex.h"
- #include "profile.h"
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <errno.h>
- #include <string.h>
- #include <time.h>
- #include <ctype.h>
- #ifndef MIN
- #define MIN(a,b) (((a)<(b))?(a):(b))
- #endif
- #define BASE64 64
- #define Q_BASE64 640
- #define BASE16 16
- #ifndef BASEX
- #define BASEX BASE16
- #endif
- #if BASEX == Q_BASE64
- #warning Q_BASE64
- #define B_ENC q_base64_enc
- #define B_DEC q_base64_dec
- #define B_ENC_LEN(l) (((l)+2)/3*4)
- #elif BASEX == BASE16
- #warning BASE16
- #define B_ENC base16_enc
- #define B_DEC base16_dec
- #define B_ENC_LEN(l) ((l)*2)
- #else
- #warning BASE64
- #define B_ENC base64_enc
- #define B_DEC base64_dec
- #define B_ENC_LEN(l) (((l)+2)/3*4)
- #endif
- #define QUOTE_MACRO(x) QUOTEME(x)
- #define QUOTEME(x) #x
- static char* id="$Id$";
- static char* version="basex test 0.1 "
- "BASE" QUOTE_MACRO(BASEX) ": " QUOTE_MACRO(B_ENC) ", " QUOTE_MACRO(B_DEC) ""
- #if defined BASE64_LOOKUP_TABLE
- #ifdef BASE64_LOOKUP_LARGE
- " (large b64 lookup table)"
- #else
- " (lookup b64 table)"
- #endif
- #else
- " (no b64 lookup table)"
- #endif
- #if defined BASE16_LOOKUP_TABLE
- #ifdef BASE16_LOOKUP_LARGE
- " (large b16 lookup table)"
- #else
- " (lookup b16 table)"
- #endif
- #else
- " (no b16 lookup table)"
- #endif
- #if defined BASE64_READ_WHOLE_INTS || defined BASE16_READ_WHOLE_INTS
- " (read 4 bytes at a time)"
- #else
- " (read 1 byte at a time)"
- #endif
- ;
- static char* help_msg="\
- Usage: basex [-hv] ... [options]\n\
- Options:\n\
- -m min minimum length\n\
- -M max maximum length\n\
- -o offset offset from the start of the buffer (alignment tests)\n\
- -e offset offset from the start of the dst. buf. (alignment tests)\n\
- -n no. number of test loops\n\
- -v increase verbosity\n\
- -V version number\n\
- -h this help message\n\
- ";
- /* profiling */
- struct profile_data pf1, pf2, pf3, pf4, pf5, pf6;
- void dump_profile_info(struct profile_data* pd)
- {
- printf("profiling for %s (%ld/%ld): %lld/%lld/%lld (max/avg/last),"
- " total %lld\n",
- pd->name, pd->entries, pd->exits, pd->max_cycles,
- pd->entries?pd->total_cycles/pd->entries:0, pd->cycles,
- pd->total_cycles);
- }
- int seed_prng()
- {
- int seed, rfd;
- if ((rfd=open("/dev/urandom", O_RDONLY))!=-1){
- try_again:
- if (read(rfd, (void*)&seed, sizeof(seed))==-1){
- if (errno==EINTR) goto try_again; /* interrupted by signal */
- fprintf(stderr, "WARNING: could not read from /dev/urandom: "
- " %s (%d)\n", strerror(errno), errno);
- }
- close(rfd);
- }else{
- fprintf(stderr, "WARNING: could not open /dev/urandom: %s (%d)\n",
- strerror(errno), errno);
- }
- seed+=getpid()+time(0);
- srand(seed);
- return 0;
- }
- /* fill buf with random data*/
- void fill_rand(unsigned char* buf, int len)
- {
- unsigned char* end;
- int v;
- /* find out how many random bytes we can get from rand() */
- #if RAND_MAX >= 0xffffffff
- #define RAND_BYTES 4
- #warning RAND_BYTES is 4
- #elif RAND_MAX >= 0xffffff
- #define RAND_BYTES 3
- #warning RAND_BYTES is 3
- #elif RAND_MAX >= 0xffff
- #define RAND_BYTES 2
- #warning RAND_BYTES is 2
- #else
- #define RAND_BYTES 1
- #endif
- end=buf+len/RAND_BYTES*RAND_BYTES;
- for(;buf<end;buf+=RAND_BYTES){
- v=rand();
- buf[0]=v;
- #if RAND_BYTES > 1
- buf[1]=v>>8;
- #endif
- #if RAND_BYTES > 2
- buf[2]=v>>16;
- #endif
- #if RAND_BYTES > 4
- buf[3]=v>>24;
- #endif
- }
- v=rand();
- switch(end-buf){
- case 3:
- #if RAND_BYTES > 2
- buf[2]=v>>16;
- #else
- buf[2]=rand();
- #endif
- case 2:
- #if RAND_BYTES > 1
- buf[1]=v>>8;
- #else
- buf[1]=rand();
- #endif
- case 1:
- buf[0]=v;
- case 0:
- break;
- }
- }
- int main(int argc, char** argv)
- {
- int loops, min_len, max_len, offset, e_offset;
- unsigned char* ibuf;
- unsigned char* enc_buf;
- unsigned char* dec_buf;
- int ibuf_len, enc_buf_len, dec_buf_len;
- int offs, c_len, e_len, l;
- int r;
- int verbose;
- int c;
- char* tmp;
- verbose=0;
- min_len=max_len=offset=-1;
- e_offset=0;
- loops=1024;
- opterr=0;
- while ((c=getopt(argc, argv, "n:m:M:o:e:vhV"))!=-1){
- switch(c){
- case 'n':
- loops=strtol(optarg, &tmp, 0);
- if ((tmp==0)||(*tmp)||(loops<0)){
- fprintf(stderr, "bad number: -%c %s\n", c, optarg);
- goto error;
- }
- break;
- case 'm':
- min_len=strtol(optarg, &tmp, 0);
- if ((tmp==0)||(*tmp)||(min_len<0)){
- fprintf(stderr, "bad number: -%c %s\n", c, optarg);
- goto error;
- }
- break;
- case 'M':
- max_len=strtol(optarg, &tmp, 0);
- if ((tmp==0)||(*tmp)||(max_len<0)){
- fprintf(stderr, "bad number: -%c %s\n", c, optarg);
- goto error;
- }
- break;
- case 'o':
- offset=strtol(optarg, &tmp, 0);
- if ((tmp==0)||(*tmp)||(offset<0)){
- fprintf(stderr, "bad number: -%c %s\n", c, optarg);
- goto error;
- }
- break;
- case 'e':
- e_offset=strtol(optarg, &tmp, 0);
- if ((tmp==0)||(*tmp)||(e_offset<0)){
- fprintf(stderr, "bad number: -%c %s\n", c, optarg);
- goto error;
- }
- break;
- case 'v':
- verbose++;
- break;
- case 'V':
- printf("version: %s\n", version);
- printf("%s\n", id);
- exit(0);
- break;
- case 'h':
- printf("version: %s\n", version);
- printf("%s", help_msg);
- exit(0);
- break;
- case '?':
- if (isprint(optopt))
- fprintf(stderr, "Unknown option `-%c\n", optopt);
- else
- fprintf(stderr, "Unknown character `\\x%x\n", optopt);
- goto error;
- case ':':
- fprintf(stderr, "Option `-%c requires an argument.\n",
- optopt);
- goto error;
- break;
- default:
- abort();
- }
- }
- if (min_len==-1 && max_len==-1){
- min_len=0;
- max_len=4*1024*1024;
- }else if (min_len==-1)
- min_len=0;
- else if (max_len==-1)
- max_len=min_len;
- /* init */
- ibuf_len=max_len;
- ibuf=malloc(ibuf_len);
- if (ibuf==0){
- fprintf(stderr, "ERROR: 1. memory allocation error (%d bytes)\n",
- ibuf_len);
- exit(-1);
- }
- enc_buf_len=B_ENC_LEN(ibuf_len);
- enc_buf=malloc(enc_buf_len+e_offset);
- if (enc_buf==0){
- fprintf(stderr, "ERROR: 2. memory allocation error (%d bytes)\n",
- enc_buf_len);
- exit(-1);
- }
- enc_buf+=e_offset; /* make sure it's off by e_offset bytes from the
- aligned stuff malloc returns */
- dec_buf_len=ibuf_len;
- dec_buf=malloc(dec_buf_len+e_offset);
- if (dec_buf==0){
- fprintf(stderr, "ERROR: 3. memory allocation error (%d bytes)\n",
- dec_buf_len+e_offset);
- exit(-1);
- }
- dec_buf+=e_offset; /* make sure it's off by e_offset bytes from the
- aligned stuff malloc returns */
- seed_prng();
- /* profile */
- profile_init(&pf1, "encode");
- profile_init(&pf2, "decode");
- init_basex();
- if (verbose)
- printf("starting (loops %d, min size %d, max size %d, offset %d,"
- ", e_offset %d, buffer sizes %d %d %d)\n",
- loops, min_len, max_len, offset, e_offset, ibuf_len,
- enc_buf_len, dec_buf_len);
- for (r=0; r<loops; r++){
- if (min_len!=max_len)
- /* test encode/decode random data w/ random length*/
- c_len= min_len+(int)((float)(max_len-min_len+1)*
- (rand()/(RAND_MAX+1.0)));
- else
- /* test encode /decode random data w/ fixed length*/
- c_len=max_len;
- if (offset==-1)
- /* offset between 0 & MIN(clen,3) */
- offs= (int)((float)(MIN(c_len,3)+1)*(rand()/(RAND_MAX+1.0)));
- else if (offset>c_len)
- offs=0;
- else
- offs=offset;
- if (verbose>2)
- printf("loop %d, current len %d, offset %d, start %p\n",
- r, c_len-offs, offs, &ibuf[offs]);
- else if ((verbose >1) && (r %10==0)) putchar('.');
- fill_rand(ibuf, c_len);
- c_len-=offs;
- e_len=B_ENC_LEN(c_len);
- profile_start(&pf1);
- l=B_ENC(&ibuf[offs], c_len, enc_buf, e_len);
- profile_end(&pf1);
- if (l != e_len){
- fprintf(stderr, "ERROR: invalid length for encoding: %d "
- "instead of %d (loops=%d)\n", l, e_len, r);
- exit(-1);
- }
- profile_start(&pf2);
- l=B_DEC(enc_buf, e_len, dec_buf, c_len);
- profile_end(&pf2);
- if (l != c_len){
- fprintf(stderr, "ERROR: invalid length for decoding: %d "
- "instead of %d (loops=%d)\n", l, c_len, r);
- exit(-1);
- }
- if (memcmp(&ibuf[offs], dec_buf, c_len)!=0){
- fprintf(stderr, "ERROR: decoding mismatch "
- "(loops=%d, c_len=%d)\n", r, c_len);
- abort();
- exit(-1);
- }
- }
- if (verbose >1) putchar('\n');
- /* encode len data and decode it, print profiling info*/
- dump_profile_info(&pf1);
- dump_profile_info(&pf2);
- return 0;
- error:
- exit(-1);
- }
|