[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