/* $Id: consistency.c,v 1.8 2005/07/30 08:43:01 soyt Exp $ ****************************************************************************** This is a consistency-test application. Written in 1998 by Andreas Beck [becka@ggi-project.org] This software is placed in the public domain and can be used freely for any purpose. It comes without any kind of warranty, either expressed or implied, including, but not limited to the implied warranties of merchantability or fitness for a particular purpose. Use it at your own risk. the author is not responsible for any damage or consequences raised by use or inability to use this program. ****************************************************************************** */ #include "config.h" #include #include #include #include #include /* If this flag is set, break out early when inconsitencies are detected. * This is useful for quick-checks, while for fixing things, it is often * more useful to get _all_ error messages. */ static enum flags { BREAK_UNCONSISTENT=1, /* Stop consistency tests when a few failures have been recorded */ } flags = 0; /* Global data about the opened visual and the mode on it. */ static struct { ggi_visual_t vis; int sx,sy,vx,vy; } mode; /**********************************************************************/ /* The pixelvalue of the color "white". */ static ggi_pixel white_pixel, black_pixel; /* Print the name of the currently running test in the top left corner */ static void TestName(const char *name) { ggiSetGCForeground(mode.vis,white_pixel); ggiPuts(mode.vis,0,0,name); } /* This gets the number of pixels with a nonzero pixelvalue within the * rectangle enclosed by x1,y2,x2,y2 - including both borders. */ static int getnumpixels(int x1,int y1,int x2,int y2) { int x,y,c; ggi_pixel pix; c=0; for (y=y1; y <= y2; y++) { for (x=x1; x <= x2; x++) { ggiGetPixel(mode.vis, x, y, &pix); if (pix != 0) c++; } } return c; } /* That is just an arbitrary value, that ensures we always get the same * pseudo-random sequence. */ #define RANDSEED 0x12345678 /* Draw a random sequence into a rectangle. */ static void drawrandom(int x1,int y1,int x2,int y2) { int x,y; srand(RANDSEED); for (y=y1; y<=y2; y++) { for (x=x1; x<=x2; x++) { if (rand()&1) ggiDrawPixel(mode.vis,x,y); } } } /* Check, if the pixels set in a rectangle are those that would have been * drawn by the above routine. */ static int checkrandom(int x1,int y1,int x2,int y2) { int x, y; ggi_pixel pix; srand(RANDSEED); for (y=y1; y<=y2; y++) { for (x=x1; x<=x2; x++) { ggiGetPixel(mode.vis, x, y, &pix); if (!pix != !(rand()&1)) return 1; } } return 0; } /* A few very basic checks, that test the checking system itself. * If these fail, something is _very_ wrong. */ static void BasicConsistency(void) { int c,x,y,pass; ggi_pixel rc; ggi_pixel pix; fprintf(stderr,"Consistency: Testing GC color get/set ... "); pass=1; for(x=1;x!=0;x<<=1) { ggiSetGCForeground(mode.vis, (ggi_pixel)x); ggiGetGCForeground(mode.vis,&rc); if ((unsigned)x != rc) { pass=0;break; } } if (pass) fprintf(stderr,"passed.\n"); else fprintf(stderr,"failed at %x.\n",x); /* Get/Put/DrawPixel consistency test */ ggiSetGCForeground(mode.vis, black_pixel); ggiFillscreen(mode.vis); /* The screen should now be all zero. */ c=0; for (y=0;y 16) { fprintf(stderr, "Error: Screen not blank or GetPixel not working. Consitency checks useless.\n"); y=mode.vy; break; } } } } } /* Most targets have a continuous range of possible color values, and loop * at the end. As soon as we set something larger than the maximum, we get * back the modulus (usually 0). We check if, and when that happens. * The output is neither pass/fail, nor does it indicate much, but it * can be helpful to target developers. */ static void ColorWrap(void) { ggi_pixel pix, pix2; /* Now we check when we have a color wraparound. */ fprintf(stderr, "Consistency: Testing color wraparound ... "); for (pix=0; pix != 0xffffffff; pix++) { ggiPutPixel(mode.vis, 0, 0, pix); ggiGetPixel(mode.vis, 0, 0, &pix2); if (pix != pix2) { fprintf(stderr, "at %08x.\n", pix); break; } } if (pix == 0xffffffff) fprintf(stderr,"none\n"); } /* Test horizontal lines. */ static void Hline(void) { int x,y,c,pass; TestName("Hline"); ggiSetGCForeground(mode.vis, black_pixel); ggiFillscreen(mode.vis); pass=1; fprintf(stderr,"Consistency: Testing HLine ... "); for (x=0;xmax) max=abs(y2-y1); if (max==0) return 0; for (xx=0;xx<=max;xx++) { cx=(x1*xx+x2*(max-xx)+max/2)/max; cy=(y1*xx+y2*(max-xx)+max/2)/max; ggiGetPixel (vis, cx, cy, &pix); if (pix == 0) { fprintf(stderr, "Line: Unset pixel %d,%d in line(%d,%d,%d,%d).\n", cx,cy,x1,y1,x2,y2); fail = 1; if (flags&BREAK_UNCONSISTENT) break; } ggiDrawPixel(vis,cx,cy); } if ((pix = getnumpixels(0,0,120,120)) != black_pixel) { fprintf(stderr, "Line: %d surplus pixels in line(%d,%d,%d,%d).\n", pix,x1,y1,x2,y2); ggiFillscreen(vis); fail=1; } return fail; } /* Do an exhaustive check for correctly working line(). Note, that it is * important to check _all_ directions. This might not be complete, as there * could be errors at specific major lengths, which are not completely checked. * Maybe we should add a few more ... */ static void Line(void) { int x,failcnt; fprintf(stderr,"Consistency: Testing Line ... "); failcnt=0; ggiSetGCForeground(mode.vis, black_pixel); ggiFillscreen(mode.vis); for (x=10;x<110;x++) failcnt+=CheckLine(mode.vis, 10, 10,x,110); for (x=10;x<110;x++) failcnt+=CheckLine(mode.vis, 10, 10,110,x); for (x=10;x<110;x++) failcnt+=CheckLine(mode.vis,110, 10,x,110); for (x=10;x<110;x++) failcnt+=CheckLine(mode.vis,110, 10, 10,x); for (x=10;x<110;x++) failcnt+=CheckLine(mode.vis, 10,110,x, 10); for (x=10;x<110;x++) failcnt+=CheckLine(mode.vis, 10,110,110,x); for (x=10;x<110;x++) failcnt+=CheckLine(mode.vis,110,110,x, 10); for (x=10;x<110;x++) failcnt+=CheckLine(mode.vis,110,110, 10,x); if (failcnt==0) fprintf(stderr,"passed.\n"); else fprintf(stderr,"failed.\n"); } /* Check boxes. */ static void Box(void) { int x,y,c,pass; pass=1; fprintf(stderr,"Consistency: Testing box height=0 ... "); ggiSetGCForeground(mode.vis, black_pixel); ggiFillscreen(mode.vis); /* Degenerate case - height=0 */ for (x=0;x