[cairo-commit] cairo/test .cvsignore, 1.22, 1.23 buffer-diff.c, 1.3, 1.4 buffer-diff.h, 1.2, 1.3 cairo-test.c, 1.21, 1.22 cairo-test.h, 1.7, 1.8 read-png.c, 1.3, 1.4 xmalloc.h, 1.1, 1.2

Carl Worth commit at pdx.freedesktop.org
Wed Apr 27 13:33:27 PDT 2005


Committed by: cworth

Update of /cvs/cairo/cairo/test
In directory gabe:/tmp/cvs-serv19572/test

Modified Files:
	.cvsignore buffer-diff.c buffer-diff.h cairo-test.c 
	cairo-test.h read-png.c xmalloc.h 
Log Message:

        * test/.cvsignore:
        * test/buffer-diff.c: (xunlink), (buffer_diff), (image_diff):
        * test/buffer-diff.h:
        * test/cairo-test.c: (set_image_target), (cleanup_image_target),
        (set_glitz_target), (cleanup_glitz_target), (set_quartz_target),
        (cleanup_quartz_target), (set_win32_target),
        (cleanup_win32_target), (set_xcb_target), (cleanup_xcb_target),
        (set_xlib_target), (cleanup_xlib_target), (cairo_test_for_target),
        (cairo_test_real), (cairo_test_expect_failure), (cairo_test):
        * test/cairo-test.h:
        * test/read-png.c: (read_png_argb32):
        * test/xmalloc.h: Add support for testing multiple backends,
        courtesy of cairo_surface_write_to_png. Currently, only image and
        xlib backends are fullk hooked-up, but other backends should be
        quite easy to add for anyone skilled in the appropriate art.


Index: .cvsignore
===================================================================
RCS file: /cvs/cairo/cairo/test/.cvsignore,v
retrieving revision 1.22
retrieving revision 1.23
diff -u -d -r1.22 -r1.23
--- .cvsignore	27 Apr 2005 01:56:37 -0000	1.22
+++ .cvsignore	27 Apr 2005 20:33:25 -0000	1.23
@@ -29,7 +29,8 @@
 translate-show-surface
 trap-clip
 user-data
-*-out.png
+*_image-out.png
+*_xlib-out.png
 *-diff.png
 *.la
 *.lo

Index: buffer-diff.c
===================================================================
RCS file: /cvs/cairo/cairo/test/buffer-diff.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- buffer-diff.c	4 Apr 2005 16:47:12 -0000	1.3
+++ buffer-diff.c	27 Apr 2005 20:33:25 -0000	1.4
@@ -23,22 +23,37 @@
  *
  * Author: Richard D. Worth <richard at theworths.org> */
 
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+
 #include "buffer-diff.h"
+#include "read-png.h"
+#include "write-png.h"
+#include "xmalloc.h"
+
+static void
+xunlink (const char *pathname)
+{
+    if (unlink (pathname) < 0 && errno != ENOENT) {
+	fprintf (stderr, "  Error: Cannot remove %s: %s\n",
+		 pathname, strerror (errno));
+	exit (1);
+    }
+}
 
-/* Image comparison code courttesy of Richard Worth.
- * Returns number of pixels changed.
- * Also fills out a "diff" image intended to visually show where the
- * images differ.
- */
 int
 buffer_diff (unsigned char *buf_a,
 	     unsigned char *buf_b,
 	     unsigned char *buf_diff,
-	     int width, int height, int stride)
+	     int	    width,
+	     int	    height,
+	     int	    stride)
 {
     int x, y;
-    int total_pixels_changed = 0;
     unsigned char *row_a, *row_b, *row;
+    int pixels_changed = 0;
 
     for (y = 0; y < height; y++)
     {
@@ -49,19 +64,19 @@
 	{
 	    int channel;
 	    unsigned char value_a, value_b;
-	    int pixel_changed = 0;
+	    int pixel_differs = 0;
 	    for (channel = 0; channel < 4; channel++)
 	    {
 		double diff;
 		value_a = row_a[x * 4 + channel];
 		value_b = row_b[x * 4 + channel];
 		if (value_a != value_b)
-		    pixel_changed = 1;
+		    pixel_differs = 1;
 		diff = value_a - value_b;
 		row[x * 4 + channel] = 128 + diff / 3.0;
 	    }
-	    if (pixel_changed) {
-		total_pixels_changed++;
+	    if (pixel_differs) {
+		pixels_changed++;
 	    } else {
 		row[x*4+0] = 0;
 		row[x*4+1] = 0;
@@ -71,5 +86,64 @@
 	}
     }
 
-    return total_pixels_changed;
+    return pixels_changed;
+}
+
+/* Image comparison code courtesy of Richard Worth <richard at theworths.org>
+ * Returns number of pixels changed, (or -1 on error).
+ * Also saves a "diff" image intended to visually show where the
+ * images differ.
+ */
+int
+image_diff (const char *filename_a,
+	    const char *filename_b,
+	    const char *filename_diff)
+{
+    int pixels_changed;
+    unsigned int width_a, height_a, stride_a;
+    unsigned int width_b, height_b, stride_b;
+    unsigned char *buf_a, *buf_b, *buf_diff;
+    read_png_status_t status;
+
+    status = read_png_argb32 (filename_a, &buf_a, &width_a, &height_a, &stride_a);
+    if (status)
+	return -1;
+
+    status = read_png_argb32 (filename_b, &buf_b, &width_b, &height_b, &stride_b);
+    if (status)
+	return -1;
+
+    if (width_a  != width_b  ||
+	height_a != height_b ||
+	stride_a != stride_b)
+    {
+	fprintf (stderr,
+		 "Error: Image size mismatch: (%dx%d@%d) vs. (%dx%d@%d)\n"
+		 "       for %s vs. %s\n",
+		 width_a, height_a, stride_a,
+		 width_b, height_b, stride_b,
+		 filename_a, filename_b);
+	free (buf_a);
+	free (buf_b);
+	return -1;
+    }
+
+    buf_diff = xcalloc (stride_a * height_a, 1);
+
+    pixels_changed = buffer_diff (buf_a, buf_b, buf_diff,
+				  width_a, height_a, stride_a);
+
+    if (pixels_changed) {
+	FILE *png_file = fopen (filename_diff, "wb");
+	write_png_argb32 (buf_diff, png_file, width_a, height_a, stride_a);
+	fclose (png_file);
+    } else {
+	xunlink (filename_diff);
+    }
+
+    free (buf_a);
+    free (buf_b);
+    free (buf_diff);
+
+    return pixels_changed;
 }

Index: buffer-diff.h
===================================================================
RCS file: /cvs/cairo/cairo/test/buffer-diff.h,v
retrieving revision 1.2
retrieving revision 1.3
diff -u -d -r1.2 -r1.3
--- buffer-diff.h	4 Apr 2005 16:47:12 -0000	1.2
+++ buffer-diff.h	27 Apr 2005 20:33:25 -0000	1.3
@@ -26,15 +26,25 @@
 #ifndef BUFFER_DIFF_H
 #define BUFFER_DIFF_H
 
-/* Image comparison code courttesy of Richard Worth.
- * Returns number of pixels changed.
- * Also fills out a "diff" image intended to visually show where the
+/* Returns number of pixels changed, (or -1 on error).
+ * Also fills in a "diff" buffer intended to visually show where the
  * images differ.
  */
 int
 buffer_diff (unsigned char *buf_a,
 	     unsigned char *buf_b,
 	     unsigned char *buf_diff,
-	     int width, int height, int stride);
+	     int	    width,
+	     int	    height,
+	     int	    stride);
+
+/* Returns number of pixels changed, (or -1 on error).
+ * Also saves a "diff" image intended to visually show where the
+ * images differ.
+ */
+int
+image_diff (const char *filename_a,
+	    const char *filename_b,
+	    const char *filename_diff);
 
 #endif

Index: cairo-test.c
===================================================================
RCS file: /cvs/cairo/cairo/test/cairo-test.c,v
retrieving revision 1.21
retrieving revision 1.22
diff -u -d -r1.21 -r1.22
--- cairo-test.c	26 Apr 2005 16:43:39 -0000	1.21
+++ cairo-test.c	27 Apr 2005 20:33:25 -0000	1.22
@@ -95,75 +95,201 @@
     }
 }
 
-cairo_test_status_t
-cairo_test_expect_failure (cairo_test_t		      *test, 
-			   cairo_test_draw_function_t  draw,
-			   const char		      *because)
+typedef cairo_test_status_t
+(*cairo_test_set_target_t) (cairo_t *cr, int width, int height, void **closure);
+
+typedef void
+(*cairo_test_cleanup_target_t) (void *closure);
+
+typedef struct _cairo_test_target
 {
-    printf ("%s is expected to fail:\n\t%s\n", test->name, because);
-    return cairo_test (test, draw);
+    const char		       *name;
+    cairo_test_set_target_t	set_target;
+    cairo_test_cleanup_target_t cleanup_target;
+    void		       *closure;
+} cairo_test_target_t;
+
+static cairo_test_status_t
+set_image_target (cairo_t *cr, int width, int height, void **closure)
+{
+    unsigned char *png_buf;
+    int stride = 4 * width;
+
+    png_buf = xcalloc (stride * height, 1);
+
+    cairo_set_target_image (cr, png_buf, CAIRO_FORMAT_ARGB32,
+			    width, height, stride);
+
+    *closure = png_buf;
+
+    return CAIRO_TEST_SUCCESS;
 }
 
-cairo_test_status_t
-cairo_test (cairo_test_t *test, cairo_test_draw_function_t draw)
+static void
+cleanup_image_target (void *closure)
+{
+    unsigned char *png_buf = closure;
+
+    free (png_buf);
+}
+
+/* XXX: Someone who knows glitz better than I do should fix this up to
+ * work. */
+#if 0 /* #ifdef CAIRO_HAS_GLITZ_SURFACE */
+static cairo_test_status_t
+set_glitz_target (cairo_t *cr, int width, int height, void **closure)
+{
+#error Not yet implemented
+}
+
+static void
+cleanup_glitz_target (cairo_t *cr)
+{
+#error Not yet implemented
+}
+#endif
+
+#ifdef CAIRO_HAS_QUARTZ_SURFACE
+static cairo_test_status_t
+set_quartz_target (cairo_t *cr, int width, int height, void **closure)
+{
+#error Not yet implemented
+}
+
+static void
+cleanup_quartz_target (void *closure)
+{
+#error Not yet implemented
+}
+#endif
+
+#ifdef CAIRO_HAS_WIN32_SURFACE
+static cairo_test_status_t
+set_win32_target (cairo_t *cr, int width, int height, void **closure)
+{
+#error Not yet implemented
+}
+
+static void
+cleanup_win32_target (void *closure)
+{
+#error Not yet implemented
+}
+#endif
+
+#ifdef CAIRO_HAS_XCB_SURFACE
+static cairo_test_status_t
+set_xcb_target (cairo_t *cr, int width, int height, void **closure)
+{
+#error Not yet implemented
+}
+
+static void
+cleanup_xcb_target (void *closure)
+{
+#error Not yet implemented
+}
+#endif
+
+#ifdef CAIRO_HAS_XLIB_SURFACE
+typedef struct _xlib_target_closure
+{
+    Display *dpy;
+    Pixmap pixmap;
+} xlib_target_closure_t;
+
+static cairo_test_status_t
+set_xlib_target (cairo_t *cr, int width, int height, void **closure)
+{
+    xlib_target_closure_t *xtc;
+    cairo_surface_t *surface;
+    Display *dpy;
+
+    *closure = xtc = xmalloc (sizeof (xlib_target_closure_t));
+
+    xtc->dpy = dpy = XOpenDisplay (0);
+    if (xtc->dpy == NULL) {
+	fprintf (stderr, "Failed to open display: %s\n", XDisplayName(0));
+	return CAIRO_TEST_FAILURE;
+    }
+
+    xtc->pixmap = XCreatePixmap (dpy, DefaultRootWindow (dpy),
+				 width, height, 32);
+
+    surface = cairo_xlib_surface_create_for_pixmap (dpy, xtc->pixmap,
+						    CAIRO_FORMAT_ARGB32);
+    cairo_xlib_surface_set_size (surface, width, height);
+    cairo_set_target_surface (cr, surface);
+
+    return CAIRO_TEST_SUCCESS;
+}
+
+static void
+cleanup_xlib_target (void *closure)
+{
+    xlib_target_closure_t *xtc = closure;
+
+    XFreePixmap (xtc->dpy, xtc->pixmap);
+    XCloseDisplay (xtc->dpy);
+}
+#endif
+
+static cairo_test_status_t
+cairo_test_for_target (cairo_test_t *test,
+		       cairo_test_draw_function_t draw,
+		       cairo_test_target_t	 *target)
 {
     cairo_test_status_t status;
     cairo_t *cr;
-    int stride;
-    unsigned char *png_buf, *ref_buf, *diff_buf;
-    char *log_name, *png_name, *ref_name, *diff_name;
+    char *png_name, *ref_name, *diff_name;
     char *srcdir;
     int pixels_changed;
-    unsigned int ref_width, ref_height, ref_stride;
-    read_png_status_t png_status;
     cairo_test_status_t ret;
-    FILE *png_file;
-    FILE *log_file;
 
     /* Get the strings ready that we'll need. */
     srcdir = getenv ("srcdir");
     if (!srcdir)
 	srcdir = ".";
-    xasprintf (&log_name, "%s%s", test->name, CAIRO_TEST_LOG_SUFFIX);
-    xasprintf (&png_name, "%s%s", test->name, CAIRO_TEST_PNG_SUFFIX);
-    xasprintf (&ref_name, "%s/%s%s", srcdir, test->name, CAIRO_TEST_REF_SUFFIX);
-    xasprintf (&diff_name, "%s%s", test->name, CAIRO_TEST_DIFF_SUFFIX);
-
-    xunlink (log_name);
+    xasprintf (&png_name, "%s_%s%s", test->name,
+	       target->name, CAIRO_TEST_PNG_SUFFIX);
+    xasprintf (&ref_name, "%s/%s%s", srcdir, test->name,
+	       CAIRO_TEST_REF_SUFFIX);
+    xasprintf (&diff_name, "%s_%s%s", test->name,
+	       target->name, CAIRO_TEST_DIFF_SUFFIX);
 
     /* Run the actual drawing code. */
     cr = cairo_create ();
 
-    stride = 4 * test->width;
-
-    png_buf = xcalloc (stride * test->height, 1);
-    diff_buf = xcalloc (stride * test->height, 1);
+    status = (target->set_target) (cr,
+				   test->width, test->height,
+				   &target->closure);
+    if (status) {
+	fprintf (stderr, "Error: Failed to set %s target\n", target->name);
+	return CAIRO_TEST_FAILURE;
+    }
 
-    cairo_set_target_image (cr, png_buf, CAIRO_FORMAT_ARGB32,
-			    test->width, test->height, stride);
+    cairo_save (cr);
+    cairo_set_source_rgba (cr, 0, 0, 0, 0);
+    cairo_set_operator (cr, CAIRO_OPERATOR_SRC);
+    cairo_paint (cr);
+    cairo_restore (cr);
 
     status = (draw) (cr, test->width, test->height);
 
     /* Then, check all the different ways it could fail. */
     if (status) {
-	log_file = fopen (log_name, "a");
-	fprintf (log_file, "Error: Function under test failed\n");
-	fclose (log_file);
+	fprintf (stderr, "Error: Function under test failed\n");
 	return status;
     }
 
     if (cairo_status (cr) != CAIRO_STATUS_SUCCESS) {
-	log_file = fopen (log_name, "a");
-	fprintf (log_file, "Error: Function under test left cairo status in an error state: %s\n", cairo_status_string (cr));
-	fclose (log_file);
+	fprintf (stderr, "Error: Function under test left cairo status in an error state: %s\n", cairo_status_string (cr));
 	return CAIRO_TEST_FAILURE;
     }
 
     /* Skip image check for tests with no image (width,height == 0,0) */
     if (test->width == 0 || test->height == 0) {
 	cairo_destroy (cr);
-	free (png_buf);
-	free (diff_buf);
 	return CAIRO_TEST_SUCCESS;
     }
 
@@ -171,66 +297,19 @@
 
     cairo_destroy (cr);
 
-    ref_buf = NULL;
-    png_status = (read_png_argb32 (ref_name, &ref_buf, &ref_width, &ref_height, &ref_stride));
-    if (png_status) {
-	log_file = fopen (log_name, "a");
-	switch (png_status)
-	{
-	case READ_PNG_FILE_NOT_FOUND:
-	    fprintf (log_file, "Error: No reference image found: %s\n", ref_name);
-	    break;
-	case READ_PNG_FILE_NOT_PNG:
-	    fprintf (log_file, "Error: %s is not a png image\n", ref_name);
-	    break;
-	default:
-	    fprintf (log_file, "Error: Failed to read %s\n", ref_name);
-	}
-	fclose (log_file);
-		
-	ret = CAIRO_TEST_FAILURE;
-	goto BAIL;
-    } else {
-    }
-
-    if (test->width != ref_width || test->height != ref_height) {
-	log_file = fopen (log_name, "a");
-	fprintf (log_file,
-		 "Error: Image size mismatch: (%dx%d) vs. (%dx%d)\n"
-		 "       for %s vs %s\n",
-		 test->width, test->height,
-		 ref_width, ref_height,
-		 png_name, ref_name);
-	fclose (log_file);
+    target->cleanup_target (target->closure);
 
-	ret = CAIRO_TEST_FAILURE;
-	goto BAIL;
-    }
+    pixels_changed = image_diff (png_name, ref_name, diff_name);
 
-    pixels_changed = buffer_diff (png_buf, ref_buf, diff_buf,
-				  test->width, test->height, stride);
     if (pixels_changed) {
-	log_file = fopen (log_name, "a");
-	fprintf (log_file, "Error: %d pixels differ from reference image %s\n",
-		 pixels_changed, ref_name);
-	png_file = fopen (diff_name, "wb");
-	write_png_argb32 (diff_buf, png_file, test->width, test->height, stride);
-	fclose (png_file);
-	fclose (log_file);
-
 	ret = CAIRO_TEST_FAILURE;
-	goto BAIL;
+	if (pixels_changed > 0)
+	    fprintf (stderr, "Error: %d pixels differ from reference image %s\n",
+		     pixels_changed, ref_name);
     } else {
-	xunlink (diff_name);
+	ret = CAIRO_TEST_SUCCESS;
     }
 
-    ret = CAIRO_TEST_SUCCESS;
-
-BAIL:
-    free (png_buf);
-    free (ref_buf);
-    free (diff_buf);
-    free (log_name);
     free (png_name);
     free (ref_name);
     free (diff_name);
@@ -238,6 +317,74 @@
     return ret;
 }
 
+static cairo_test_status_t
+cairo_test_real (cairo_test_t *test, cairo_test_draw_function_t draw)
+{
+    int i;
+    FILE *stderr_saved = stderr;
+    cairo_test_status_t status, ret;
+    cairo_test_target_t targets[] = 
+	{
+	    { "image", set_image_target, cleanup_image_target}, 
+#if 0 /* #ifdef CAIRO_HAS_GLITZ_SURFACE */
+	    { "glitz", set_glitz_target, cleanup_glitz_target}, 
+#endif
+#ifdef CAIRO_HAS_QUARTZ_SURFACE
+	    { "quartz", set_quartz_target, cleanup_quart_target},
+#endif
+#ifdef CAIRO_HAS_WIN32_SURFACE
+	    { "win32", set_win32_target, cleanup_win32_target},
+#endif
+#ifdef CAIRO_HAS_XCB_SURFACE
+	    { "xcb", set_xcb_target, cleanup_xcb_target},
+#endif
+#ifdef CAIRO_HAS_XLIB_SURFACE
+	    { "xlib", set_xlib_target, cleanup_xlib_target},
+#endif
+	};
+    char *log_name;
+
+    xasprintf (&log_name, "%s%s", test->name, CAIRO_TEST_LOG_SUFFIX);
+    xunlink (log_name);
+
+    stderr = fopen (log_name, "a");
+
+    ret = CAIRO_TEST_SUCCESS;
+    for (i=0; i < sizeof(targets)/sizeof(targets[0]); i++) {
+	cairo_test_target_t *target = &targets[i];
+	fprintf (stderr, "Testing %s with %s target\n", test->name, target->name);
+	printf ("%s_%s:\t", test->name, target->name);
+	status = cairo_test_for_target (test, draw, target);
+	if (status) {
+	    printf ("FAIL\n");
+	    ret = status;
+	} else {
+	    printf ("PASS\n");
+	}
+    }
+
+    fclose (stderr);
+    stderr = stderr_saved;
+
+    return ret;
+}
+
+cairo_test_status_t
+cairo_test_expect_failure (cairo_test_t		      *test, 
+			   cairo_test_draw_function_t  draw,
+			   const char		      *because)
+{
+    printf ("\n%s is expected to fail:\n\t%s\n", test->name, because);
+    return cairo_test_real (test, draw);
+}
+
+cairo_test_status_t
+cairo_test (cairo_test_t *test, cairo_test_draw_function_t draw)
+{
+    printf ("\n");
+    return cairo_test_real (test, draw);
+}
+
 cairo_pattern_t *
 cairo_test_create_png_pattern (cairo_t *cr, const char *filename)
 {

Index: cairo-test.h
===================================================================
RCS file: /cvs/cairo/cairo/test/cairo-test.h,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- cairo-test.h	26 Apr 2005 16:43:39 -0000	1.7
+++ cairo-test.h	27 Apr 2005 20:33:25 -0000	1.8
@@ -29,6 +29,7 @@
 #include <math.h>
 #include <cairo.h>
 #include <cairo-pdf.h>
+#include <cairo-xlib.h>
 
 typedef enum cairo_test_status {
     CAIRO_TEST_SUCCESS = 0,

Index: read-png.c
===================================================================
RCS file: /cvs/cairo/cairo/test/read-png.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -d -r1.3 -r1.4
--- read-png.c	29 Mar 2005 08:02:19 -0000	1.3
+++ read-png.c	27 Apr 2005 20:33:25 -0000	1.4
@@ -76,12 +76,14 @@
 
     file = fopen (filename, "rb");
     if (file == NULL) {
+	fprintf (stderr, "Error: File not found: %s\n", filename);
 	return READ_PNG_FILE_NOT_FOUND;
     }
 
     sig_bytes = fread (png_sig, 1, PNG_SIG_SIZE, file);
     if (png_check_sig (png_sig, sig_bytes) == 0) {
         fclose (file);
+	fprintf (stderr, "Error: File is not a PNG image: %s\n", filename);
 	return READ_PNG_FILE_NOT_PNG;
     }
 
@@ -92,6 +94,7 @@
                                   NULL);
     if (png == NULL) {
         fclose (file);
+	fprintf (stderr, "Error: Out of memory while reading %s\n", filename);
 	return READ_PNG_NO_MEMORY;
     }
 
@@ -99,6 +102,7 @@
     if (info == NULL) {
         fclose (file);
         png_destroy_read_struct (&png, NULL, NULL);
+	fprintf (stderr, "Error: Out of memory while reading %s\n", filename);
 	return READ_PNG_NO_MEMORY;
     }
 

Index: xmalloc.h
===================================================================
RCS file: /cvs/cairo/cairo/test/xmalloc.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- xmalloc.h	26 Oct 2004 21:38:43 -0000	1.1
+++ xmalloc.h	27 Apr 2005 20:33:25 -0000	1.2
@@ -26,6 +26,8 @@
 #ifndef _XMALLOC_H_
 #define _XMALLOC_H_
 
+#include <stdlib.h>
+
 void *
 xmalloc (size_t size);
 




More information about the cairo-commit mailing list