/*
* recenteditor_data.c
*
* A programmers editor
*
* Tests (ensure correct functionality of modules)
*
* Author: Dario Rodriguez dario@softhome.net
* This program is licensed under the terms of GNU GPL v2.1+
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <limits.h>
#include <fcntl.h>
#include <errno.h>
#include "recenteditor_data.h"
#define PREFIX "retest_"
#define TEST_OK "OK"
typedef struct test_t {
char *name;
char *(*fn)(redata_t *,char *,char *, int, int);
char *param1;
char *param2;
int int1;
int int2;
} test_t;
static char *malloc_data(int size, int seed);
static int write_file(char *filename, char *buf, int buflen);
char *test_newfile(redata_t *redata, char *filename, char *dummy, int filesize, int dummy2);
char *test_edit(redata_t *redata, char *filename, char *edits, int filesize, int seed);
int
main(int argc, char *argv[])
{
test_t tests[]={
{"newfile_16",test_newfile,PREFIX "FILE", NULL, 16, 0},
{"newfile_1024",test_newfile,PREFIX "FILE", NULL, 1024, 0},
{"newfile_32767",test_newfile,PREFIX "FILE", NULL, 32767, 0},
{"newfile_32768",test_newfile,PREFIX "FILE", NULL, 32768, 0},
{"newfile_32769",test_newfile,PREFIX "FILE", NULL, 32769, 0},
{"newfile_131072",test_newfile,PREFIX "FILE", NULL, 131072, 0},
{"testedit_add",test_edit,PREFIX "EDIT", "A,0,$,Testing add$",0,0},
};
redata_t *redata;
int i;
int nerrors;
char *res;
for(i=0,nerrors=0;i<(sizeof(tests)/sizeof(tests[0]));i++) {
if((redata=redata_init())==NULL) {
fprintf(stderr,"ERROR: problem initializing redata module\n");
return(1);
}
fprintf(stderr,"%s...",tests[i].name);
res=tests[i].fn(redata,tests[i].param1,tests[i].param2,tests[i].int1,tests[i].int2);
if(strcmp(res,TEST_OK)==0) {
fprintf(stderr," ok.\n");
} else {
fprintf(stderr," ERROR: %s\n",res);
nerrors++;
}
redata_free(redata),redata=NULL;
}
fprintf(stderr,"\n");
if(nerrors==0)
fprintf(stderr,"All tests passed OK\n");
else
fprintf(stderr,"%i test(s) failed of %i tests run.\n",nerrors,i);
redata_free(redata),redata=NULL;
return((nerrors==0)?0:1);
}
static char *
malloc_data(int size, int seed)
{
char *mem;
int i;
if(size<=0 || (mem=malloc(size))==NULL)
return(NULL);
memset(mem,0,size);
if(seed==0) {
for(i=0;i<size;i++)
((unsigned char *)mem)[i]=(i%256);
} else {
srandom(*((unsigned int *)(&seed)));
for(i=0;i<size;i++)
((unsigned char *)mem)[i]=(random()&0xff);
}
return(mem);
}
static int
write_file(char *filename, char *buf, int buflen)
{
int fd;
if((fd=open(filename,O_WRONLY|O_CREAT|O_TRUNC,0644))==-1) {
free(buf),buf=NULL;
return(-1);
}
write(fd,buf,buflen);
close(fd),fd=-1;
return(0);
}
char *
test_newfile(redata_t *redata, char *filename, char *dummy, int filesize, int dummy2)
{
char *mem;
char hash129_pre[129];
char hash129_post[129];
fprintf(stderr,"\ntest_newfile(%s%s%s,%s%s%s,%i,%i);\nResult: ",(filename!=NULL)?"\"":"",(filename!=NULL)?filename:"NULL",(filename!=NULL)?"\"":"",(dummy!=NULL)?"\"":"",(dummy!=NULL)?dummy:"NULL",(dummy!=NULL)?"\"":"",filesize,dummy2);
/* prepare file for loading */
if((mem=malloc_data(filesize,0))==NULL)
return("insuf. mem. for temp. buffer");
if(write_file(filename,mem,filesize)==-1)
return("couldn't create temporary file");
redata_filehash(redata,filename,hash129_pre);
free(mem),mem=NULL;
/* load file */
if(redata_load(redata,filename,0)!=0) {
unlink(filename);
return("couldn't load file");
}
unlink(filename);
redata_hash(redata,hash129_post);
if(strcmp(hash129_pre,hash129_post)!=0)
return("loaded file is corrupted");
/* save file */
redata_save(redata,filename);
hash129_post[0]='\0';
redata_filehash(redata,filename,hash129_post);
if(strcmp(hash129_pre,hash129_post)!=0)
return("saved file is corrupted");
unlink(filename);
return(TEST_OK);
}
char *
test_edit(redata_t *redata, char *filename, char *edits, int filesize, int seed)
{
static char errorbuf[256];
char progress[256];
int k;
int cursize;
char *ptr;
int l;
char *mem;
char endcode;
char *ptrend;
int size;
char hash129_memold[129];
char hash129_mem[129];
char hash129_redata[129];
mem=NULL;
fprintf(stderr,"\ntest_edit(%s%s%s,%s%s%s,%i,%i);\nResult: ",(filename!=NULL)?"\"":"",(filename!=NULL)?filename:"NULL",(filename!=NULL)?"\"":"",(edits!=NULL)?"\"":"",(edits!=NULL)?edits:"NULL",(edits!=NULL)?"\"":"",filesize,seed);
/* two passes: k==0 count needed memory, k==1 do edits */
for(k=0,cursize=filesize,progress[0]='\0';k<2;k++,cursize=0,progress[0]='\0') {
for(ptr=edits;*ptr!='\0';) {
if(k!=0) {
redata_memhash(redata,mem,cursize,hash129_memold);
}
if((l=strlen(progress))<(sizeof(progress)-1)) {
progress[l]=(l<(sizeof(progress)-2))?*ptr:'+';
progress[l+1]='\0';
}
if(*ptr=='A') {
/* A,<insertpos>,<endchar>,<text><endchar> */
ptr++;
ptr+=(*ptr==',')?1:0;
errno=0;
l=(int)strtol(ptr,&ptr,10);
if(errno!=0 || l<0 || l>cursize) {
if(mem!=NULL)
free(mem),mem=NULL;
return("test_edit(): error parsing position");
}
ptr+=(*ptr==',')?1:0;
endcode=*ptr;
ptr+=(*ptr!='\0')?1:0;
ptrend=strchr(ptr,endcode);
ptrend=(ptrend==NULL)?ptr+strlen(ptr):ptrend;
size=ptrend-ptr;
if(k!=0) {
/* editing */
memmove(mem+l+size,mem+l,cursize-l);
memcpy(mem+l,ptr,size);
redata_op_add(redata,ptr,size,l);
}
cursize+=size;
ptr+=size;
ptr+=(*ptr!='\0')?1:0;
} else {
if(mem!=NULL)
free(mem),mem=NULL;
snprintf(errorbuf,sizeof(errorbuf),
"test_edit(): unknown edit action at pos %i: '%c' (progress: %s)",(int) (ptr-edits),*ptr,progress);
errorbuf[sizeof(errorbuf)-1]='\0';
return(errorbuf);
}
if(k!=0) {
redata_hash(redata,hash129_redata);
redata_memhash(redata,mem,cursize,hash129_mem);
if(strcmp(hash129_redata,hash129_mem)!=0) {
if(mem!=NULL)
free(mem),mem=NULL;
snprintf(errorbuf,sizeof(errorbuf),
"corrupted edit before pos %i (progress: %s)",(int) (ptr-edits),progress);
errorbuf[sizeof(errorbuf)-1]='\0';
return(errorbuf);
}
redata_op_undo(redata);
redata_hash(redata,hash129_redata);
if(strcmp(hash129_redata,hash129_memold)!=0) {
if(mem!=NULL)
free(mem),mem=NULL;
snprintf(errorbuf,sizeof(errorbuf),
"corrupted undo before pos %i (progress: %s)",(int) (ptr-edits),progress);
errorbuf[sizeof(errorbuf)-1]='\0';
return(errorbuf);
}
redata_op_redo(redata);
redata_hash(redata,hash129_redata);
if(strcmp(hash129_redata,hash129_mem)!=0) {
if(mem!=NULL)
free(mem),mem=NULL;
snprintf(errorbuf,sizeof(errorbuf),
"corrupted redo before pos %i (progress: %s)",(int) (ptr-edits),progress);
errorbuf[sizeof(errorbuf)-1]='\0';
return(errorbuf);
}
}
}
if(k==0) {
/* reserve memory, do init */
if((mem=malloc_data(cursize,seed))==NULL)
return("insuf. mem. for temp. buffer");
if(write_file(filename,mem,filesize)==-1)
return("couldn't create temporary file");
if(redata_load(redata,filename,0)!=0) {
unlink(filename);
return("couldn't load file");
}
unlink(filename);
}
}
if(mem!=NULL)
free(mem),mem=NULL;
return(TEST_OK);
}