You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
kamailio/test/basex.c

402 lines
9.0 KiB

/*
* $Id$
*
* 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 lenght*/
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);
}