Blame test/encodingstest.c

Packit Service b05338
#ifdef __STRICT_ANSI__
Packit Service b05338
#define _BSD_SOURCE
Packit Service b05338
#endif
Packit Service b05338
#include <time.h>
Packit Service b05338
#include <stdarg.h>
Packit Service b05338
#include <rfb/rfb.h>
Packit Service b05338
#include <rfb/rfbclient.h>
Packit Service b05338
Packit Service b05338
#ifndef LIBVNCSERVER_HAVE_LIBPTHREAD
Packit Service b05338
#error This test need pthread support (otherwise the client blocks the client)
Packit Service b05338
#endif
Packit Service b05338
Packit Service b05338
#define ALL_AT_ONCE
Packit Service b05338
/*#define VERY_VERBOSE*/
Packit Service b05338
Packit Service b05338
static MUTEX(frameBufferMutex);
Packit Service b05338
Packit Service b05338
typedef struct { int id; char* str; } encoding_t;
Packit Service b05338
static encoding_t testEncodings[]={
Packit Service b05338
        { rfbEncodingRaw, "raw" },
Packit Service b05338
	{ rfbEncodingRRE, "rre" },
Packit Service b05338
	{ rfbEncodingCoRRE, "corre" },
Packit Service b05338
	{ rfbEncodingHextile, "hextile" },
Packit Service b05338
	{ rfbEncodingUltra, "ultra" },
Packit Service b05338
#ifdef LIBVNCSERVER_HAVE_LIBZ
Packit Service b05338
	{ rfbEncodingZlib, "zlib" },
Packit Service b05338
	{ rfbEncodingZlibHex, "zlibhex" },
Packit Service b05338
	{ rfbEncodingZRLE, "zrle" },
Packit Service b05338
	{ rfbEncodingZYWRLE, "zywrle" },
Packit Service b05338
#ifdef LIBVNCSERVER_HAVE_LIBJPEG
Packit Service b05338
	{ rfbEncodingTight, "tight" },
Packit Service b05338
#endif
Packit Service b05338
#endif
Packit Service b05338
	{ 0, NULL }
Packit Service b05338
};
Packit Service b05338
Packit Service b05338
#define NUMBER_OF_ENCODINGS_TO_TEST (sizeof(testEncodings)/sizeof(encoding_t)-1)
Packit Service b05338
/*#define NUMBER_OF_ENCODINGS_TO_TEST 1*/
Packit Service b05338
Packit Service b05338
/* Here come the variables/functions to handle the test output */
Packit Service b05338
Packit Service b05338
static const int width=400,height=300;
Packit Service b05338
static unsigned int statistics[2][NUMBER_OF_ENCODINGS_TO_TEST];
Packit Service b05338
static unsigned int totalFailed,totalCount;
Packit Service b05338
static unsigned int countGotUpdate;
Packit Service b05338
static MUTEX(statisticsMutex);
Packit Service b05338
Packit Service b05338
static void initStatistics(void) {
Packit Service b05338
	memset(statistics[0],0,sizeof(int)*NUMBER_OF_ENCODINGS_TO_TEST);
Packit Service b05338
	memset(statistics[1],0,sizeof(int)*NUMBER_OF_ENCODINGS_TO_TEST);
Packit Service b05338
	totalFailed=totalCount=0;
Packit Service b05338
	INIT_MUTEX(statisticsMutex);
Packit Service b05338
}
Packit Service b05338
Packit Service b05338
Packit Service b05338
static void updateStatistics(int encodingIndex,rfbBool failed) {
Packit Service b05338
	LOCK(statisticsMutex);
Packit Service b05338
	if(failed) {
Packit Service b05338
		statistics[1][encodingIndex]++;
Packit Service b05338
		totalFailed++;
Packit Service b05338
	}
Packit Service b05338
	statistics[0][encodingIndex]++;
Packit Service b05338
	totalCount++;
Packit Service b05338
	countGotUpdate++;
Packit Service b05338
	UNLOCK(statisticsMutex);
Packit Service b05338
}
Packit Service b05338
Packit Service b05338
/* Here begin the functions for the client. They will be called in a
Packit Service b05338
 * pthread. */
Packit Service b05338
Packit Service b05338
/* maxDelta=0 means they are expected to match exactly;
Packit Service b05338
 * maxDelta>0 means that the average difference must be lower than maxDelta */
Packit Service b05338
static rfbBool doFramebuffersMatch(rfbScreenInfo* server,rfbClient* client,
Packit Service b05338
		int maxDelta)
Packit Service b05338
{
Packit Service b05338
	int i,j,k;
Packit Service b05338
	unsigned int total=0,diff=0;
Packit Service b05338
	if(server->width!=client->width || server->height!=client->height)
Packit Service b05338
		return FALSE;
Packit Service b05338
	LOCK(frameBufferMutex);
Packit Service b05338
	/* TODO: write unit test for colour transformation, use here, too */
Packit Service b05338
	for(i=0;i<server->width;i++)
Packit Service b05338
		for(j=0;j<server->height;j++)
Packit Service b05338
			for(k=0;k<3/*server->serverFormat.bitsPerPixel/8*/;k++) {
Packit Service b05338
				unsigned char s=server->frameBuffer[k+i*4+j*server->paddedWidthInBytes];
Packit Service b05338
				unsigned char cl=client->frameBuffer[k+i*4+j*client->width*4];
Packit Service b05338
Packit Service b05338
				if(maxDelta==0 && s!=cl) {
Packit Service b05338
					UNLOCK(frameBufferMutex);
Packit Service b05338
					return FALSE;
Packit Service b05338
				} else {
Packit Service b05338
					total++;
Packit Service b05338
					diff+=(s>cl?s-cl:cl-s);
Packit Service b05338
				}
Packit Service b05338
			}
Packit Service b05338
	UNLOCK(frameBufferMutex);
Packit Service b05338
	if(maxDelta>0 && diff/total>=maxDelta)
Packit Service b05338
		return FALSE;
Packit Service b05338
	return TRUE;
Packit Service b05338
}
Packit Service b05338
Packit Service b05338
static rfbBool resize(rfbClient* cl) {
Packit Service b05338
	if(cl->frameBuffer)
Packit Service b05338
		free(cl->frameBuffer);
Packit Service b05338
	cl->frameBuffer=malloc(cl->width*cl->height*cl->format.bitsPerPixel/8);
Packit Service b05338
	if(!cl->frameBuffer)
Packit Service b05338
		return FALSE;
Packit Service b05338
	SendFramebufferUpdateRequest(cl,0,0,cl->width,cl->height,FALSE);
Packit Service b05338
	return TRUE;
Packit Service b05338
}
Packit Service b05338
Packit Service b05338
typedef struct clientData {
Packit Service b05338
	int encodingIndex;
Packit Service b05338
	rfbScreenInfo* server;
Packit Service b05338
	char* display;
Packit Service b05338
} clientData;
Packit Service b05338
Packit Service b05338
static void update(rfbClient* client,int x,int y,int w,int h) {
Packit Service b05338
#ifndef VERY_VERBOSE
Packit Service b05338
Packit Service b05338
	static const char* progress="|/-\\";
Packit Service b05338
	static int counter=0;
Packit Service b05338
Packit Service b05338
	if(++counter>sizeof(progress)) counter=0;
Packit Service b05338
	fprintf(stderr,"%c\r",progress[counter]);
Packit Service b05338
#else
Packit Service b05338
	clientData* cd=(clientData*)client->clientData;
Packit Service b05338
	rfbClientLog("Got update (encoding=%s): (%d,%d)-(%d,%d)\n",
Packit Service b05338
			testEncodings[cd->encodingIndex].str,
Packit Service b05338
			x,y,x+w,y+h);
Packit Service b05338
#endif
Packit Service b05338
}
Packit Service b05338
Packit Service b05338
static void update_finished(rfbClient* client) {
Packit Service b05338
	clientData* cd=(clientData*)client->clientData;
Packit Service b05338
        int maxDelta=0;
Packit Service b05338
Packit Service b05338
#ifdef LIBVNCSERVER_HAVE_LIBZ
Packit Service b05338
	if(testEncodings[cd->encodingIndex].id==rfbEncodingZYWRLE)
Packit Service b05338
		maxDelta=5;
Packit Service b05338
#ifdef LIBVNCSERVER_HAVE_LIBJPEG
Packit Service b05338
	if(testEncodings[cd->encodingIndex].id==rfbEncodingTight)
Packit Service b05338
		maxDelta=5;
Packit Service b05338
#endif
Packit Service b05338
#endif
Packit Service b05338
	updateStatistics(cd->encodingIndex,
Packit Service b05338
			!doFramebuffersMatch(cd->server,client,maxDelta));
Packit Service b05338
}
Packit Service b05338
Packit Service b05338
Packit Service b05338
static void* clientLoop(void* data) {
Packit Service b05338
	rfbClient* client=(rfbClient*)data;
Packit Service b05338
	clientData* cd=(clientData*)client->clientData;
Packit Service b05338
Packit Service b05338
	client->appData.encodingsString=strdup(testEncodings[cd->encodingIndex].str);
Packit Service b05338
	client->appData.qualityLevel = 7; /* ZYWRLE fails the test with standard settings */
Packit Service b05338
Packit Service b05338
	sleep(1);
Packit Service b05338
	rfbClientLog("Starting client (encoding %s, display %s)\n",
Packit Service b05338
			testEncodings[cd->encodingIndex].str,
Packit Service b05338
			cd->display);
Packit Service b05338
	if(!rfbInitClient(client,NULL,NULL)) {
Packit Service b05338
		rfbClientErr("Had problems starting client (encoding %s)\n",
Packit Service b05338
				testEncodings[cd->encodingIndex].str);
Packit Service b05338
		updateStatistics(cd->encodingIndex,TRUE);
Packit Service b05338
		return NULL;
Packit Service b05338
	}
Packit Service b05338
	while(1) {
Packit Service b05338
		if(WaitForMessage(client,50)>=0)
Packit Service b05338
			if(!HandleRFBServerMessage(client))
Packit Service b05338
				break;
Packit Service b05338
	}
Packit Service b05338
	free(((clientData*)client->clientData)->display);
Packit Service b05338
	free(client->clientData);
Packit Service b05338
	client->clientData = NULL;
Packit Service b05338
	if(client->frameBuffer)
Packit Service b05338
		free(client->frameBuffer);
Packit Service b05338
	rfbClientCleanup(client);
Packit Service b05338
	return NULL;
Packit Service b05338
}
Packit Service b05338
Packit Service b05338
static pthread_t all_threads[NUMBER_OF_ENCODINGS_TO_TEST];
Packit Service b05338
static int thread_counter;
Packit Service b05338
Packit Service b05338
static void startClient(int encodingIndex,rfbScreenInfo* server) {
Packit Service b05338
	rfbClient* client=rfbGetClient(8,3,4);
Packit Service b05338
	clientData* cd;
Packit Service b05338
Packit Service b05338
	client->clientData=malloc(sizeof(clientData));
Packit Service b05338
	client->MallocFrameBuffer=resize;
Packit Service b05338
	client->GotFrameBufferUpdate=update;
Packit Service b05338
	client->FinishedFrameBufferUpdate=update_finished;
Packit Service b05338
Packit Service b05338
	cd=(clientData*)client->clientData;
Packit Service b05338
	cd->encodingIndex=encodingIndex;
Packit Service b05338
	cd->server=server;
Packit Service b05338
	cd->display=(char*)malloc(6);
Packit Service b05338
	sprintf(cd->display,":%d",server->port-5900);
Packit Service b05338
Packit Service b05338
	pthread_create(&all_threads[thread_counter++],NULL,clientLoop,(void*)client);
Packit Service b05338
}
Packit Service b05338
Packit Service b05338
/* Here begin the server functions */
Packit Service b05338
Packit Service b05338
static void idle(rfbScreenInfo* server)
Packit Service b05338
{
Packit Service b05338
	int c;
Packit Service b05338
	rfbBool goForward;
Packit Service b05338
Packit Service b05338
	LOCK(statisticsMutex);
Packit Service b05338
#ifdef ALL_AT_ONCE
Packit Service b05338
	goForward=(countGotUpdate==NUMBER_OF_ENCODINGS_TO_TEST);
Packit Service b05338
#else
Packit Service b05338
	goForward=(countGotUpdate==1);
Packit Service b05338
#endif
Packit Service b05338
Packit Service b05338
	UNLOCK(statisticsMutex);
Packit Service b05338
	if(!goForward)
Packit Service b05338
	  return;
Packit Service b05338
	countGotUpdate=0;
Packit Service b05338
Packit Service b05338
	LOCK(frameBufferMutex);
Packit Service b05338
	{
Packit Service b05338
		int i,j;
Packit Service b05338
		int x1=(rand()%(server->width-1)),x2=(rand()%(server->width-1)),
Packit Service b05338
		y1=(rand()%(server->height-1)),y2=(rand()%(server->height-1));
Packit Service b05338
		if(x1>x2) { i=x1; x1=x2; x2=i; }
Packit Service b05338
		if(y1>y2) { i=y1; y1=y2; y2=i; }
Packit Service b05338
		x2++; y2++;
Packit Service b05338
		for(c=0;c<3;c++) {
Packit Service b05338
			for(i=x1;i
Packit Service b05338
				for(j=y1;j
Packit Service b05338
					server->frameBuffer[i*4+c+j*server->paddedWidthInBytes]=255*(i-x1+j-y1)/(x2-x1+y2-y1);
Packit Service b05338
		}
Packit Service b05338
		rfbMarkRectAsModified(server,x1,y1,x2,y2);
Packit Service b05338
Packit Service b05338
#ifdef VERY_VERBOSE
Packit Service b05338
		rfbLog("Sent update (%d,%d)-(%d,%d)\n",x1,y1,x2,y2);
Packit Service b05338
#endif
Packit Service b05338
	}
Packit Service b05338
	UNLOCK(frameBufferMutex);
Packit Service b05338
}
Packit Service b05338
Packit Service b05338
/* log function (to show what messages are from the client) */
Packit Service b05338
Packit Service b05338
static void
Packit Service b05338
rfbTestLog(const char *format, ...)
Packit Service b05338
{
Packit Service b05338
	va_list args;
Packit Service b05338
	char buf[256];
Packit Service b05338
	time_t log_clock;
Packit Service b05338
Packit Service b05338
	if(!rfbEnableClientLogging)
Packit Service b05338
		return;
Packit Service b05338
Packit Service b05338
	va_start(args, format);
Packit Service b05338
Packit Service b05338
	time(&log_clock);
Packit Service b05338
	strftime(buf, 255, "%d/%m/%Y %X (client) ", localtime(&log_clock));
Packit Service b05338
	fprintf(stderr,"%s",buf);
Packit Service b05338
Packit Service b05338
	vfprintf(stderr, format, args);
Packit Service b05338
	fflush(stderr);
Packit Service b05338
Packit Service b05338
	va_end(args);
Packit Service b05338
}
Packit Service b05338
Packit Service b05338
/* the main function */
Packit Service b05338
Packit Service b05338
int main(int argc,char** argv)
Packit Service b05338
{
Packit Service b05338
	int i,j;
Packit Service b05338
	time_t t;
Packit Service b05338
	rfbScreenInfoPtr server;
Packit Service b05338
Packit Service b05338
	rfbClientLog=rfbTestLog;
Packit Service b05338
	rfbClientErr=rfbTestLog;
Packit Service b05338
Packit Service b05338
	/* Initialize server */
Packit Service b05338
	server=rfbGetScreen(&argc,argv,width,height,8,3,4);
Packit Service b05338
        if(!server)
Packit Service b05338
          return 0;
Packit Service b05338
Packit Service b05338
	server->frameBuffer=malloc(400*300*4);
Packit Service b05338
	server->cursor=NULL;
Packit Service b05338
	for(j=0;j<400*300*4;j++)
Packit Service b05338
		server->frameBuffer[j]=j;
Packit Service b05338
	rfbInitServer(server);
Packit Service b05338
	rfbProcessEvents(server,0);
Packit Service b05338
Packit Service b05338
	initStatistics();
Packit Service b05338
Packit Service b05338
#ifndef ALL_AT_ONCE
Packit Service b05338
	for(i=0;i
Packit Service b05338
#else
Packit Service b05338
	/* Initialize clients */
Packit Service b05338
	for(i=0;i
Packit Service b05338
#endif
Packit Service b05338
		startClient(i,server);
Packit Service b05338
Packit Service b05338
	t=time(NULL);
Packit Service b05338
	/* test 20 seconds */
Packit Service b05338
	while(time(NULL)-t<20) {
Packit Service b05338
Packit Service b05338
		idle(server);
Packit Service b05338
Packit Service b05338
		rfbProcessEvents(server,1);
Packit Service b05338
	}
Packit Service b05338
	rfbLog("%d failed, %d received\n",totalFailed,totalCount);
Packit Service b05338
#ifndef ALL_AT_ONCE
Packit Service b05338
	{
Packit Service b05338
		rfbClientPtr cl;
Packit Service b05338
		rfbClientIteratorPtr iter=rfbGetClientIterator(server);
Packit Service b05338
		while((cl=rfbClientIteratorNext(iter)))
Packit Service b05338
			rfbCloseClient(cl);
Packit Service b05338
		rfbReleaseClientIterator(iter);
Packit Service b05338
	}
Packit Service b05338
	}
Packit Service b05338
#endif
Packit Service b05338
Packit Service b05338
	/* shut down server, disconnecting all clients */
Packit Service b05338
	rfbShutdownServer(server, TRUE);
Packit Service b05338
Packit Service b05338
	for(i=0;i
Packit Service b05338
		pthread_join(all_threads[i], NULL);
Packit Service b05338
Packit Service b05338
	free(server->frameBuffer);
Packit Service b05338
	rfbScreenCleanup(server);
Packit Service b05338
Packit Service b05338
	rfbLog("Statistics:\n");
Packit Service b05338
	for(i=0;i
Packit Service b05338
		rfbLog("%s encoding: %d failed, %d received\n",
Packit Service b05338
				testEncodings[i].str,statistics[1][i],statistics[0][i]);
Packit Service b05338
	if(totalFailed)
Packit Service b05338
		return 1;
Packit Service b05338
	return(0);
Packit Service b05338
}
Packit Service b05338
Packit Service b05338