compiles, 1st run is okay, 2nd and subsequent give errors. Evidently,

libvncclient is not yet reentrant (or threadsafe).
pull/1/head
dscho 20 years ago
parent 31d0617d3d
commit 8715a8ab42

@ -6,37 +6,48 @@
//#error This test need pthread support (otherwise the client blocks the client) //#error This test need pthread support (otherwise the client blocks the client)
#endif #endif
//#define ALL_AT_ONCE
//#define VERY_VERBOSE
MUTEX(frameBufferMutex); MUTEX(frameBufferMutex);
int testEncodings[]={ typedef struct { int id; char* str; } encoding_t;
rfbEncodingRaw, encoding_t testEncodings[]={
rfbEncodingRRE, { rfbEncodingRaw, "raw" },
rfbEncodingCoRRE, { rfbEncodingRRE, "rre" },
rfbEncodingHextile, { rfbEncodingCoRRE, "corre" },
{ rfbEncodingHextile, "hextile" },
#ifdef LIBVNCSERVER_HAVE_LIBZ #ifdef LIBVNCSERVER_HAVE_LIBZ
rfbEncodingZlib, { rfbEncodingZlib, "zlib" },
rfbEncodingZlibHex, { rfbEncodingZlibHex, "zlibhex" },
rfbEncodingZRLE, { rfbEncodingZRLE, "zrle" },
#ifdef LIBVNCSERVER_HAVE_LIBJPEG #ifdef LIBVNCSERVER_HAVE_LIBJPEG
rfbEncodingTight, { rfbEncodingTight, "tight" },
#endif #endif
#endif #endif
0 { 0, 0 }
}; };
#define NUMBER_OF_ENCODINGS_TO_TEST (sizeof(testEncodings)/sizeof(int)-1) #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 */ /* Here come the variables/functions to handle the test output */
const int width=400,height=300;
struct { int x1,y1,x2,y2; } lastUpdateRect; struct { int x1,y1,x2,y2; } lastUpdateRect;
unsigned int statistics[NUMBER_OF_ENCODINGS_TO_TEST]; unsigned int statistics[2][NUMBER_OF_ENCODINGS_TO_TEST];
unsigned int totalFailed; unsigned int totalFailed,totalCount;
unsigned int countGotUpdate; unsigned int countGotUpdate;
MUTEX(statisticsMutex); MUTEX(statisticsMutex);
void initStatistics() { void initStatistics() {
memset(statistics,0,sizeof(int)*NUMBER_OF_ENCODINGS_TO_TEST); memset(statistics[0],0,sizeof(int)*NUMBER_OF_ENCODINGS_TO_TEST);
totalFailed=0; 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); INIT_MUTEX(statisticsMutex);
} }
@ -53,9 +64,11 @@ void updateServerStatistics(int x1,int y1,int x2,int y2) {
void updateStatistics(int encodingIndex,rfbBool failed) { void updateStatistics(int encodingIndex,rfbBool failed) {
LOCK(statisticsMutex); LOCK(statisticsMutex);
if(failed) { if(failed) {
statistics[encodingIndex]++; statistics[1][encodingIndex]++;
totalFailed++; totalFailed++;
} }
statistics[0][encodingIndex]++;
totalCount++;
countGotUpdate++; countGotUpdate++;
UNLOCK(statisticsMutex); UNLOCK(statisticsMutex);
} }
@ -78,9 +91,9 @@ rfbBool doFramebuffersMatch(rfbScreenInfo* server,rfbClient* client,
/* TODO: write unit test for colour transformation, use here, too */ /* TODO: write unit test for colour transformation, use here, too */
for(i=0;i<server->width;i++) for(i=0;i<server->width;i++)
for(j=0;j<server->height;j++) for(j=0;j<server->height;j++)
for(k=0;k<server->serverFormat.bitsPerPixel/8;k++) { for(k=0;k<3/*server->serverFormat.bitsPerPixel/8*/;k++) {
unsigned char s=server->frameBuffer[k+i*4+j*server->paddedWidthInBytes]; unsigned char s=server->frameBuffer[k+i*4+j*server->paddedWidthInBytes];
unsigned char cl=client->frameBuffer[k+i*4+j*client->width]; unsigned char cl=client->frameBuffer[k+i*4+j*client->width*4];
if(maxDelta==0 && s!=cl) { if(maxDelta==0 && s!=cl) {
UNLOCK(frameBufferMutex); UNLOCK(frameBufferMutex);
@ -100,40 +113,69 @@ static rfbBool resize(rfbClient* cl) {
if(cl->frameBuffer) if(cl->frameBuffer)
free(cl->frameBuffer); free(cl->frameBuffer);
cl->frameBuffer=(char*)malloc(cl->width*cl->height*cl->format.bitsPerPixel/8); cl->frameBuffer=(char*)malloc(cl->width*cl->height*cl->format.bitsPerPixel/8);
SendFramebufferUpdateRequest(cl,0,0,cl->width,cl->height,FALSE);
} }
typedef struct clientData { typedef struct clientData {
int encodingIndex; int encodingIndex;
rfbScreenInfo* server; rfbScreenInfo* server;
char* display;
} clientData; } clientData;
static void update(rfbClient* client,int x,int y,int w,int h) { static void update(rfbClient* client,int x,int y,int w,int h) {
clientData* cd=(clientData*)client->clientData; clientData* cd=(clientData*)client->clientData;
int maxDelta=0; int maxDelta=0;
if(testEncodings[cd->encodingIndex]==rfbEncodingTight)
maxDelta=5;
/* TODO: check if dimensions match with marked rectangle */ /* 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 */ /* only check if this was the last update */
if(x+w!=lastUpdateRect.x2 || y+h!=lastUpdateRect.y2) 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; return;
}
if(testEncodings[cd->encodingIndex].id==rfbEncodingTight)
maxDelta=5;
updateStatistics(cd->encodingIndex, updateStatistics(cd->encodingIndex,
!doFramebuffersMatch(cd->server,client,maxDelta)); !doFramebuffersMatch(cd->server,client,maxDelta));
} }
static void* clientLoop(void* data) { static void* clientLoop(void* data) {
rfbClient* client=(rfbClient*)data; rfbClient* client=(rfbClient*)data;
int argc=2; clientData* cd=(clientData*)client->clientData;
char* argv[2]={"client",":0"}; int argc=4;
if(!rfbInitClient(client,&argc,argv)) 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; return 0;
}
while(1) { while(1) {
if(WaitForMessage(client,50)>=0) if(WaitForMessage(client,50)>=0)
if(!HandleRFBServerMessage(client)) if(!HandleRFBServerMessage(client))
break; break;
} }
free(((clientData*)client->clientData)->display);
free(client->clientData);
if(client->frameBuffer) if(client->frameBuffer)
free(client->frameBuffer); free(client->frameBuffer);
rfbClientCleanup(client); rfbClientCleanup(client);
@ -152,6 +194,8 @@ static void startClient(int encodingIndex,rfbScreenInfo* server) {
cd=(clientData*)client->clientData; cd=(clientData*)client->clientData;
cd->encodingIndex=encodingIndex; cd->encodingIndex=encodingIndex;
cd->server=server; cd->server=server;
cd->display=(char*)malloc(6);
sprintf(cd->display,":%d",server->port-5900);
pthread_create(&clientThread,NULL,clientLoop,(void*)client); pthread_create(&clientThread,NULL,clientLoop,(void*)client);
} }
@ -164,22 +208,40 @@ static void idle(rfbScreenInfo* server)
rfbBool goForward; rfbBool goForward;
LOCK(statisticsMutex); LOCK(statisticsMutex);
#ifdef ALL_AT_ONCE
goForward=(countGotUpdate==NUMBER_OF_ENCODINGS_TO_TEST); 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); UNLOCK(statisticsMutex);
if(!goForward) if(!goForward)
return; return;
countGotUpdate=0;
LOCK(frameBufferMutex); LOCK(frameBufferMutex);
for(c=0;c<3;c++) { {
int x1=(rand()%server->width),x2=(rand()%server->width),
y1=(rand()%server->height),y2=(rand()%server->height);
int i,j; 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(x1>x2) { i=x1; x1=x2; x2=i; }
if(y1>y2) { i=y1; y1=y2; y2=i; } if(y1>y2) { i=y1; y1=y2; y2=i; }
for(i=x1;i<=x2;i++) x2++; y2++;
for(j=y1;j<=y2;j++) for(c=0;c<3;c++) {
server->frameBuffer[i*4+c+j*server->paddedWidthInBytes]=255*(i-x1+j-y1+1)/(x2-x1+y2-y1+1); for(i=x1;i<x2;i++)
rfbMarkRectAsModified(server,x1,y1,x2+1,y2+1); for(j=y1;j<y2;j++)
server->frameBuffer[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); UNLOCK(frameBufferMutex);
} }
@ -192,31 +254,51 @@ int main(int argc,char** argv)
time_t t; time_t t;
/* Initialize server */ /* Initialize server */
rfbScreenInfoPtr server=rfbGetScreen(&argc,argv,400,300,8,3,4); rfbScreenInfoPtr server=rfbGetScreen(&argc,argv,width,height,8,3,4);
server->frameBuffer=malloc(400*300*4); server->frameBuffer=malloc(400*300*4);
for(j=0;j<400*300*4;j++) for(j=0;j<400*300*4;j++)
server->frameBuffer[j]=j; server->frameBuffer[j]=j;
rfbInitServer(server); rfbInitServer(server);
rfbProcessEvents(server,50); rfbProcessEvents(server,0);
initStatistics();
#ifndef ALL_AT_ONCE
for(i=0;i<NUMBER_OF_ENCODINGS_TO_TEST;i++) {
#else
/* Initialize clients */ /* Initialize clients */
for(i=0;i<NUMBER_OF_ENCODINGS_TO_TEST;i++) for(i=0;i<NUMBER_OF_ENCODINGS_TO_TEST;i++)
#endif
startClient(i,server); startClient(i,server);
t=time(0); t=time(0);
/* test 20 seconds */ /* test 20 seconds */
while(time(0)-t<20) { while(time(0)-t<5) {
idle(server); idle(server);
rfbProcessEvents(server,50); rfbProcessEvents(server,1);
}
rfbLog("%d failed, %d received\n",totalFailed,totalCount);
#ifndef ALL_AT_ONCE
{
rfbClientPtr cl;
rfbClientIteratorPtr iter=rfbGetClientIterator(server);
while((cl=rfbClientIteratorNext(iter)))
rfbCloseClient(cl);
rfbReleaseClientIterator(iter);
} }
}
#endif
free(server->frameBuffer); free(server->frameBuffer);
rfbScreenCleanup(server); rfbScreenCleanup(server);
printf("Statistics: %d failed\n",totalFailed); rfbLog("Statistics:\n");
for(i=0;i<NUMBER_OF_ENCODINGS_TO_TEST;i++)
rfbLog("%s encoding: %d failed, %d received\n",
testEncodings[i].str,statistics[1][i],statistics[0][i]);
if(totalFailed) if(totalFailed)
return 1; return 1;
return(0); return(0);

Loading…
Cancel
Save