From 5a3e352fbad43a7b673d6394ac10291b6e6fbe6b Mon Sep 17 00:00:00 2001 From: dscho Date: Sat, 16 Oct 2004 02:48:45 +0000 Subject: rename tight-1.c into encodingstest.c, fixing it in the process. It now passes all encodings except corre (broken) and zrle (not yet implemented in libvncclient) --- test/Makefile.am | 6 +- test/encodingstest.c | 345 +++++++++++++++++++++++++++++++++++++++++++++++++++ test/tight-1.c | 306 --------------------------------------------- 3 files changed, 349 insertions(+), 308 deletions(-) create mode 100644 test/encodingstest.c delete mode 100644 test/tight-1.c diff --git a/test/Makefile.am b/test/Makefile.am index 33839d5..c2d04c4 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -6,8 +6,10 @@ endif copyrecttest_LDADD=$(LDADD) -lm -noinst_PROGRAMS=tight-1 cargstest copyrecttest $(BACKGROUND_TEST) - +noinst_PROGRAMS=encodingstest cargstest copyrecttest $(BACKGROUND_TEST) LDADD = ../libvncserver/libvncserver.a ../libvncclient/libvncclient.a +test: encodingstest cargstest copyrecttest + ./encodingstest && ./cargstest + diff --git a/test/encodingstest.c b/test/encodingstest.c new file mode 100644 index 0000000..5c84caf --- /dev/null +++ b/test/encodingstest.c @@ -0,0 +1,345 @@ +#include +#include +#include +#include + +#ifndef LIBVNCSERVER_HAVE_LIBPTHREAD +#error This test need pthread support (otherwise the client blocks the client) +#endif + +#define ALL_AT_ONCE +//#define VERY_VERBOSE + +MUTEX(frameBufferMutex); + +typedef struct { int id; char* str; } encoding_t; +encoding_t testEncodings[]={ + { rfbEncodingRaw, "raw" }, + { rfbEncodingRRE, "rre" }, + /* TODO: fix corre */ + /* { rfbEncodingCoRRE, "corre" }, */ + { rfbEncodingHextile, "hextile" }, +#ifdef LIBVNCSERVER_HAVE_LIBZ + { rfbEncodingZlib, "zlib" }, + { rfbEncodingZlibHex, "zlibhex" }, + /* TODO: implement ZRLE decoding */ + /* { rfbEncodingZRLE, "zrle" }, */ +#ifdef LIBVNCSERVER_HAVE_LIBJPEG + { rfbEncodingTight, "tight" }, +#endif +#endif + { 0, 0 } +}; + +#define NUMBER_OF_ENCODINGS_TO_TEST (sizeof(testEncodings)/sizeof(encoding_t)-1) +//#define NUMBER_OF_ENCODINGS_TO_TEST 1 + +/* Here come the variables/functions to handle the test output */ + +const int width=400,height=300; +struct { int x1,y1,x2,y2; } lastUpdateRect; +unsigned int statistics[2][NUMBER_OF_ENCODINGS_TO_TEST]; +unsigned int totalFailed,totalCount; +unsigned int countGotUpdate; +MUTEX(statisticsMutex); + +void initStatistics() { + memset(statistics[0],0,sizeof(int)*NUMBER_OF_ENCODINGS_TO_TEST); + memset(statistics[1],0,sizeof(int)*NUMBER_OF_ENCODINGS_TO_TEST); + totalFailed=totalCount=0; + lastUpdateRect.x1=0; + lastUpdateRect.y1=0; + lastUpdateRect.x2=width; + lastUpdateRect.y2=height; + INIT_MUTEX(statisticsMutex); +} + +void updateServerStatistics(int x1,int y1,int x2,int y2) { + LOCK(statisticsMutex); + countGotUpdate=0; + lastUpdateRect.x1=x1; + lastUpdateRect.y1=y1; + lastUpdateRect.x2=x2; + lastUpdateRect.y2=y2; + UNLOCK(statisticsMutex); +} + +void updateStatistics(int encodingIndex,rfbBool failed) { + LOCK(statisticsMutex); + if(failed) { + statistics[1][encodingIndex]++; + totalFailed++; + } + statistics[0][encodingIndex]++; + totalCount++; + countGotUpdate++; + UNLOCK(statisticsMutex); +} + + + +/* Here begin the functions for the client. They will be called in a + * pthread. */ + +/* maxDelta=0 means they are expected to match exactly; + * maxDelta>0 means that the average difference must be lower than maxDelta */ +rfbBool doFramebuffersMatch(rfbScreenInfo* server,rfbClient* client, + int maxDelta) +{ + int i,j,k; + unsigned int total=0,diff=0; + if(server->width!=client->width || server->height!=client->height) + return FALSE; + LOCK(frameBufferMutex); + /* TODO: write unit test for colour transformation, use here, too */ + for(i=0;iwidth;i++) + for(j=0;jheight;j++) + for(k=0;k<3/*server->serverFormat.bitsPerPixel/8*/;k++) { + unsigned char s=server->frameBuffer[k+i*4+j*server->paddedWidthInBytes]; + unsigned char cl=client->frameBuffer[k+i*4+j*client->width*4]; + + if(maxDelta==0 && s!=cl) { + UNLOCK(frameBufferMutex); + return FALSE; + } else { + total++; + diff+=(s>cl?s-cl:cl-s); + } + } + UNLOCK(frameBufferMutex); + if(maxDelta>0 && diff/total>=maxDelta) + return FALSE; + return TRUE; +} + +static rfbBool resize(rfbClient* cl) { + if(cl->frameBuffer) + free(cl->frameBuffer); + cl->frameBuffer=(char*)malloc(cl->width*cl->height*cl->format.bitsPerPixel/8); + SendFramebufferUpdateRequest(cl,0,0,cl->width,cl->height,FALSE); +} + +typedef struct clientData { + int encodingIndex; + rfbScreenInfo* server; + char* display; +} clientData; + +static void update(rfbClient* client,int x,int y,int w,int h) { + clientData* cd=(clientData*)client->clientData; + int maxDelta=0; + +#ifndef VERY_VERBOSE + static const char* progress="|/-\\"; + static int counter=0; + + if(++counter>sizeof(progress)) counter=0; + fprintf(stderr,"%c\r",progress[counter]); +#else + rfbClientLog("Got update (encoding=%s): (%d,%d)-(%d,%d)\n", + testEncodings[cd->encodingIndex].str, + x,y,x+w,y+h); +#endif + + /* only check if this was the last update */ + if(x+w!=lastUpdateRect.x2 || y+h!=lastUpdateRect.y2) { +#ifdef VERY_VERBOSE + rfbClientLog("Waiting (%d!=%d or %d!=%d)\n", + x+w,lastUpdateRect.x2,y+h,lastUpdateRect.y2); +#endif + return; + } + + if(testEncodings[cd->encodingIndex].id==rfbEncodingTight) + maxDelta=5; + + updateStatistics(cd->encodingIndex, + !doFramebuffersMatch(cd->server,client,maxDelta)); +} + +static void* clientLoop(void* data) { + rfbClient* client=(rfbClient*)data; + clientData* cd=(clientData*)client->clientData; + int argc=4; + char* argv[4]={"client", + "-encodings", testEncodings[cd->encodingIndex].str, + cd->display}; + + + sleep(1); + rfbClientLog("Starting client (encoding %s, display %s)\n", + testEncodings[cd->encodingIndex].str, + cd->display); + if(!rfbInitClient(client,&argc,argv)) { + rfbClientErr("Had problems starting client (encoding %s)\n", + testEncodings[cd->encodingIndex].str); + updateStatistics(cd->encodingIndex,TRUE); + return 0; + } + while(1) { + if(WaitForMessage(client,50)>=0) + if(!HandleRFBServerMessage(client)) + break; + } + free(((clientData*)client->clientData)->display); + free(client->clientData); + if(client->frameBuffer) + free(client->frameBuffer); + rfbClientCleanup(client); + return 0; +} + +static void startClient(int encodingIndex,rfbScreenInfo* server) { + rfbClient* client=rfbGetClient(8,3,4); + clientData* cd; + pthread_t clientThread; + + client->clientData=malloc(sizeof(clientData)); + client->MallocFrameBuffer=resize; + client->GotFrameBufferUpdate=update; + + cd=(clientData*)client->clientData; + cd->encodingIndex=encodingIndex; + cd->server=server; + cd->display=(char*)malloc(6); + sprintf(cd->display,":%d",server->port-5900); + + lastUpdateRect.x1=lastUpdateRect.y1=0; + lastUpdateRect.x2=server->width; + lastUpdateRect.y2=server->height; + + pthread_create(&clientThread,NULL,clientLoop,(void*)client); +} + +/* Here begin the server functions */ + +static void idle(rfbScreenInfo* server) +{ + int c; + rfbBool goForward; + + LOCK(statisticsMutex); +#ifdef ALL_AT_ONCE + goForward=(countGotUpdate==NUMBER_OF_ENCODINGS_TO_TEST); +#else + goForward=(countGotUpdate==1); +#endif + /* if(lastUpdateRect.x2==354) + rfbLog("server checked: countGotUpdate=%d\n",countGotUpdate); */ + UNLOCK(statisticsMutex); + if(!goForward) + return; + countGotUpdate=0; + + LOCK(frameBufferMutex); + { + int i,j; + int x1=(rand()%(server->width-1)),x2=(rand()%(server->width-1)), + y1=(rand()%(server->height-1)),y2=(rand()%(server->height-1)); + if(x1>x2) { i=x1; x1=x2; x2=i; } + if(y1>y2) { i=y1; y1=y2; y2=i; } + x2++; y2++; + for(c=0;c<3;c++) { + for(i=x1;iframeBuffer[i*4+c+j*server->paddedWidthInBytes]=255*(i-x1+j-y1)/(x2-x1+y2-y1); + } + rfbMarkRectAsModified(server,x1,y1,x2,y2); + + lastUpdateRect.x1=x1; + lastUpdateRect.y1=y1; + lastUpdateRect.x2=x2; + lastUpdateRect.y2=y2; +#ifdef VERY_VERBOSE + rfbLog("Sent update (%d,%d)-(%d,%d)\n",x1,y1,x2,y2); +#endif + } + UNLOCK(frameBufferMutex); +} + +/* log function (to show what messages are from the client) */ + +void +rfbTestLog(const char *format, ...) +{ + va_list args; + char buf[256]; + time_t log_clock; + + if(!rfbEnableClientLogging) + return; + + va_start(args, format); + + time(&log_clock); + strftime(buf, 255, "%d/%m/%Y %X (client) ", localtime(&log_clock)); + fprintf(stderr,buf); + + vfprintf(stderr, format, args); + fflush(stderr); + + va_end(args); +} + +/* the main function */ + +int main(int argc,char** argv) +{ + int i,j; + time_t t; + + rfbClientLog=rfbTestLog; + rfbClientErr=rfbTestLog; + + /* Initialize server */ + rfbScreenInfoPtr server=rfbGetScreen(&argc,argv,width,height,8,3,4); + + server->frameBuffer=malloc(400*300*4); + for(j=0;j<400*300*4;j++) + server->frameBuffer[j]=j; + rfbInitServer(server); + rfbProcessEvents(server,0); + + initStatistics(); + +#ifndef ALL_AT_ONCE + for(i=0;iframeBuffer); + rfbScreenCleanup(server); + + rfbLog("Statistics:\n"); + for(i=0;i -#include -#include - -#ifndef LIBVNCSERVER_HAVE_LIBTHREAD -//#error This test need pthread support (otherwise the client blocks the client) -#endif - -//#define ALL_AT_ONCE -//#define VERY_VERBOSE - -MUTEX(frameBufferMutex); - -typedef struct { int id; char* str; } encoding_t; -encoding_t testEncodings[]={ - { rfbEncodingRaw, "raw" }, - { rfbEncodingRRE, "rre" }, - { rfbEncodingCoRRE, "corre" }, - { rfbEncodingHextile, "hextile" }, -#ifdef LIBVNCSERVER_HAVE_LIBZ - { rfbEncodingZlib, "zlib" }, - { rfbEncodingZlibHex, "zlibhex" }, - { rfbEncodingZRLE, "zrle" }, -#ifdef LIBVNCSERVER_HAVE_LIBJPEG - { rfbEncodingTight, "tight" }, -#endif -#endif - { 0, 0 } -}; - -#define NUMBER_OF_ENCODINGS_TO_TEST (sizeof(testEncodings)/sizeof(encoding_t)-1) -//#define NUMBER_OF_ENCODINGS_TO_TEST 1 - -/* Here come the variables/functions to handle the test output */ - -const int width=400,height=300; -struct { int x1,y1,x2,y2; } lastUpdateRect; -unsigned int statistics[2][NUMBER_OF_ENCODINGS_TO_TEST]; -unsigned int totalFailed,totalCount; -unsigned int countGotUpdate; -MUTEX(statisticsMutex); - -void initStatistics() { - memset(statistics[0],0,sizeof(int)*NUMBER_OF_ENCODINGS_TO_TEST); - memset(statistics[1],0,sizeof(int)*NUMBER_OF_ENCODINGS_TO_TEST); - totalFailed=totalCount=0; - lastUpdateRect.x1=0; - lastUpdateRect.y1=0; - lastUpdateRect.x2=width; - lastUpdateRect.y2=height; - INIT_MUTEX(statisticsMutex); -} - -void updateServerStatistics(int x1,int y1,int x2,int y2) { - LOCK(statisticsMutex); - countGotUpdate=0; - lastUpdateRect.x1=x1; - lastUpdateRect.y1=y1; - lastUpdateRect.x2=x2; - lastUpdateRect.y2=y2; - UNLOCK(statisticsMutex); -} - -void updateStatistics(int encodingIndex,rfbBool failed) { - LOCK(statisticsMutex); - if(failed) { - statistics[1][encodingIndex]++; - totalFailed++; - } - statistics[0][encodingIndex]++; - totalCount++; - countGotUpdate++; - UNLOCK(statisticsMutex); -} - - - -/* Here begin the functions for the client. They will be called in a - * pthread. */ - -/* maxDelta=0 means they are expected to match exactly; - * maxDelta>0 means that the average difference must be lower than maxDelta */ -rfbBool doFramebuffersMatch(rfbScreenInfo* server,rfbClient* client, - int maxDelta) -{ - int i,j,k; - unsigned int total=0,diff=0; - if(server->width!=client->width || server->height!=client->height) - return FALSE; - LOCK(frameBufferMutex); - /* TODO: write unit test for colour transformation, use here, too */ - for(i=0;iwidth;i++) - for(j=0;jheight;j++) - for(k=0;k<3/*server->serverFormat.bitsPerPixel/8*/;k++) { - unsigned char s=server->frameBuffer[k+i*4+j*server->paddedWidthInBytes]; - unsigned char cl=client->frameBuffer[k+i*4+j*client->width*4]; - - if(maxDelta==0 && s!=cl) { - UNLOCK(frameBufferMutex); - return FALSE; - } else { - total++; - diff+=(s>cl?s-cl:cl-s); - } - } - UNLOCK(frameBufferMutex); - if(maxDelta>0 && diff/total>=maxDelta) - return FALSE; - return TRUE; -} - -static rfbBool resize(rfbClient* cl) { - if(cl->frameBuffer) - free(cl->frameBuffer); - cl->frameBuffer=(char*)malloc(cl->width*cl->height*cl->format.bitsPerPixel/8); - SendFramebufferUpdateRequest(cl,0,0,cl->width,cl->height,FALSE); -} - -typedef struct clientData { - int encodingIndex; - rfbScreenInfo* server; - char* display; -} clientData; - -static void update(rfbClient* client,int x,int y,int w,int h) { - clientData* cd=(clientData*)client->clientData; - int maxDelta=0; - - /* TODO: check if dimensions match with marked rectangle */ - -#ifdef VERY_VERBOSE - rfbLog("Got update (encoding=%s): (%d,%d)-(%d,%d)\n", - testEncodings[cd->encodingIndex].str, - x,y,x+w,y+h); -#endif - - /* only check if this was the last update */ - if(x+w!=lastUpdateRect.x2 || y+h!=lastUpdateRect.y2) { -#ifdef VERY_VERBOSE - rfbLog("Waiting (%d!=%d or %d!=%d)\n", - x+w,lastUpdateRect.x2,y+h,lastUpdateRect.y2); -#endif - return; - } - - if(testEncodings[cd->encodingIndex].id==rfbEncodingTight) - maxDelta=5; - - updateStatistics(cd->encodingIndex, - !doFramebuffersMatch(cd->server,client,maxDelta)); -} - -static void* clientLoop(void* data) { - rfbClient* client=(rfbClient*)data; - clientData* cd=(clientData*)client->clientData; - int argc=4; - char* argv[4]={"client", - "-encodings", testEncodings[cd->encodingIndex].str, - cd->display}; - - - sleep(1); - rfbLog("Starting client (encoding %s, display %s)\n", - testEncodings[cd->encodingIndex].str, - cd->display); - if(!rfbInitClient(client,&argc,argv)) { - rfbLog("Had problems starting client (encoding %s)\n", - testEncodings[cd->encodingIndex].str); - updateStatistics(cd->encodingIndex,TRUE); - return 0; - } - while(1) { - if(WaitForMessage(client,50)>=0) - if(!HandleRFBServerMessage(client)) - break; - } - free(((clientData*)client->clientData)->display); - free(client->clientData); - if(client->frameBuffer) - free(client->frameBuffer); - rfbClientCleanup(client); - return 0; -} - -static void startClient(int encodingIndex,rfbScreenInfo* server) { - rfbClient* client=rfbGetClient(8,3,4); - clientData* cd; - pthread_t clientThread; - - client->clientData=malloc(sizeof(clientData)); - client->MallocFrameBuffer=resize; - client->GotFrameBufferUpdate=update; - - cd=(clientData*)client->clientData; - cd->encodingIndex=encodingIndex; - cd->server=server; - cd->display=(char*)malloc(6); - sprintf(cd->display,":%d",server->port-5900); - - pthread_create(&clientThread,NULL,clientLoop,(void*)client); -} - -/* Here begin the server functions */ - -static void idle(rfbScreenInfo* server) -{ - int c; - rfbBool goForward; - - LOCK(statisticsMutex); -#ifdef ALL_AT_ONCE - goForward=(countGotUpdate==NUMBER_OF_ENCODINGS_TO_TEST); -#else - goForward=(countGotUpdate==1); -#endif - /* if(lastUpdateRect.x2==354) - rfbLog("server checked: countGotUpdate=%d\n",countGotUpdate); */ - UNLOCK(statisticsMutex); - if(!goForward) - return; - countGotUpdate=0; - - LOCK(frameBufferMutex); - { - int i,j; - int x1=(rand()%(server->width-1)),x2=(rand()%(server->width-1)), - y1=(rand()%(server->height-1)),y2=(rand()%(server->height-1)); - if(x1>x2) { i=x1; x1=x2; x2=i; } - if(y1>y2) { i=y1; y1=y2; y2=i; } - x2++; y2++; - for(c=0;c<3;c++) { - for(i=x1;iframeBuffer[i*4+c+j*server->paddedWidthInBytes]=255*(i-x1+j-y1)/(x2-x1+y2-y1); - } - rfbMarkRectAsModified(server,x1,y1,x2,y2); - - lastUpdateRect.x1=x1; - lastUpdateRect.y1=y1; - lastUpdateRect.x2=x2; - lastUpdateRect.y2=y2; -#ifdef VERY_VERBOSE - rfbLog("Sent update (%d,%d)-(%d,%d)\n",x1,y1,x2,y2); -#endif - } - UNLOCK(frameBufferMutex); -} - -//TODO: pthread'ize the client. otherwise server and client block each -//other -int main(int argc,char** argv) -{ - int i,j; - time_t t; - - /* Initialize server */ - rfbScreenInfoPtr server=rfbGetScreen(&argc,argv,width,height,8,3,4); - - server->frameBuffer=malloc(400*300*4); - for(j=0;j<400*300*4;j++) - server->frameBuffer[j]=j; - rfbInitServer(server); - rfbProcessEvents(server,0); - - initStatistics(); - -#ifndef ALL_AT_ONCE - for(i=0;iframeBuffer); - rfbScreenCleanup(server); - - rfbLog("Statistics:\n"); - for(i=0;i