[cairo-commit] 2 commits - src/cairo.h src/cairo-surface.c test/cairo-test.c test/cairo-test.h

Behdad Esfahbod behdad at kemper.freedesktop.org
Fri Jun 30 17:07:00 PDT 2006


 src/cairo-surface.c |   30 ++++++++++++++++++++++++++
 src/cairo.h         |    5 ++--
 test/cairo-test.c   |   59 ++++++++++++++++++++++++++++++++++++++++------------
 test/cairo-test.h   |    3 +-
 4 files changed, 81 insertions(+), 16 deletions(-)

New commits:
diff-tree cfddf93afb692819548adb85c5b75f60be7e7349 (from 01b1f3572c3c15a08dd6f32788106c0e42fd2436)
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Sat Jul 1 01:55:12 2006 +0200

    Make CAIRO_EXTEND_REFLECT and CAIRO_EXTEND_PAD not crash on surface patterns,
    
    but return error.

diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index dd349c2..66f7a46 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -1178,6 +1178,12 @@ _cairo_surface_paint (cairo_surface_t	*s
 
     assert (! surface->is_snapshot);
 
+    if (source->type == CAIRO_PATTERN_TYPE_SURFACE &&
+	(source->extend == CAIRO_EXTEND_REFLECT || source->extend == CAIRO_EXTEND_PAD))
+    {
+        return CAIRO_STATUS_NO_MEMORY;
+    }
+
     _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source.base);
 
     if (surface->backend->paint) {
@@ -1206,6 +1212,12 @@ _cairo_surface_mask (cairo_surface_t	*su
 
     assert (! surface->is_snapshot);
 
+    if (source->type == CAIRO_PATTERN_TYPE_SURFACE &&
+	(source->extend == CAIRO_EXTEND_REFLECT || source->extend == CAIRO_EXTEND_PAD))
+    {
+        return CAIRO_STATUS_NO_MEMORY;
+    }
+
     _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source.base);
     _cairo_surface_copy_pattern_for_destination (mask, surface, &dev_mask.base);
 
@@ -1244,6 +1256,12 @@ _cairo_surface_stroke (cairo_surface_t		
 
     assert (! surface->is_snapshot);
 
+    if (source->type == CAIRO_PATTERN_TYPE_SURFACE &&
+	(source->extend == CAIRO_EXTEND_REFLECT || source->extend == CAIRO_EXTEND_PAD))
+    {
+        return CAIRO_STATUS_NO_MEMORY;
+    }
+
     _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source.base);
 
     if (surface->backend->stroke) {
@@ -1283,6 +1301,12 @@ _cairo_surface_fill (cairo_surface_t	*su
 
     assert (! surface->is_snapshot);
 
+    if (source->type == CAIRO_PATTERN_TYPE_SURFACE &&
+	(source->extend == CAIRO_EXTEND_REFLECT || source->extend == CAIRO_EXTEND_PAD))
+    {
+        return CAIRO_STATUS_NO_MEMORY;
+    }
+
     _cairo_surface_copy_pattern_for_destination (source, surface, &dev_source.base);
 
     if (surface->backend->fill) {
@@ -1684,6 +1708,12 @@ _cairo_surface_show_glyphs (cairo_surfac
 
     assert (! surface->is_snapshot);
 
+    if (source->type == CAIRO_PATTERN_TYPE_SURFACE &&
+	(source->extend == CAIRO_EXTEND_REFLECT || source->extend == CAIRO_EXTEND_PAD))
+    {
+        return CAIRO_STATUS_NO_MEMORY;
+    }
+
     _cairo_surface_copy_pattern_for_destination (source,
 						 surface,
 						 &dev_source.base);
diff --git a/src/cairo.h b/src/cairo.h
index d2116cb..ab860e8 100644
--- a/src/cairo.h
+++ b/src/cairo.h
@@ -1492,9 +1492,10 @@ cairo_pattern_get_matrix (cairo_pattern_
  *   are fully transparent
  * @CAIRO_EXTEND_REPEAT: the pattern is tiled by repeating
  * @CAIRO_EXTEND_REFLECT: the pattern is tiled by reflecting
- *   at the edges
+ *   at the edges (not implemented for surface patterns currently)
  * @CAIRO_EXTEND_PAD: pixels outside of the pattern copy
- *   the closest pixel from the source (Since 1.2)
+ *   the closest pixel from the source (Since 1.2; not implemented
+ *   for surface patterns currently)
  *
  * #cairo_extend_t is used to describe how the area outside
  * of a pattern will be drawn.
diff-tree 01b1f3572c3c15a08dd6f32788106c0e42fd2436 (from 19c4700101bfce7d73a50017021b4ec198ddd783)
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Fri Jun 30 22:01:24 2006 +0200

    Detect and report crashes in tests.

diff --git a/test/cairo-test.c b/test/cairo-test.c
index 651b9f0..38acd0d 100644
--- a/test/cairo-test.c
+++ b/test/cairo-test.c
@@ -31,6 +31,8 @@
 #include <stdlib.h>
 #include <stdarg.h>
 #include <ctype.h>
+#include <setjmp.h>
+#include <signal.h>
 #include <assert.h>
 #ifdef HAVE_UNISTD_H
 #include <unistd.h>
@@ -68,6 +70,12 @@ typedef enum cairo_internal_surface_type
 #define access _access
 #define F_OK 0
 #endif
+#ifndef FALSE
+#define FALSE 0
+#endif
+#ifndef TRUE
+#define TRUE !FALSE
+#endif
 
 static void
 xunlink (const char *pathname);
@@ -89,6 +97,12 @@ static const char *fail_face = "", *norm
  * general-purpose library, and it keeps the tests cleaner to avoid a
  * context object there, (though not a whole lot). */
 FILE *cairo_test_log_file = NULL;
+char *srcdir;
+
+/* Used to catch crashes in a test, such that we report it as such and
+ * continue testing, although one crasher may already have corrupted memory in
+ * an nonrecoverable fashion. */
+jmp_buf jmpbuf;
 
 void
 cairo_test_init (const char *test_name)
@@ -1463,15 +1477,11 @@ cairo_test_for_target (cairo_test_t *tes
     cairo_surface_t *surface;
     cairo_t *cr;
     char *png_name, *ref_name, *diff_name, *offset_str;
-    char *srcdir;
     char *format;
     cairo_test_status_t ret;
     cairo_content_t expected_content;
 
     /* Get the strings ready that we'll need. */
-    srcdir = getenv ("srcdir");
-    if (!srcdir)
-	srcdir = ".";
     format = _cairo_test_content_name (target->content);
 
     if (dev_offset)
@@ -1613,12 +1623,19 @@ UNWIND_STRINGS:
     return ret;
 }
 
+static void
+segfault_handler (int signal)
+{
+    longjmp (jmpbuf, signal);
+}
+
 static cairo_test_status_t
 cairo_test_expecting (cairo_test_t *test, cairo_test_draw_function_t draw,
 		      cairo_test_status_t expectation)
 {
-    int i, j, num_targets;
+    volatile int i, j, num_targets;
     const char *tname;
+    sighandler_t old_segfault_handler;
     cairo_test_status_t status, ret;
     cairo_test_target_t **targets_to_test;
     cairo_test_target_t targets[] =
@@ -1751,6 +1768,17 @@ cairo_test_expecting (cairo_test_t *test
 #endif
 	};
 
+#ifdef HAVE_UNISTD_H
+    if (isatty (1)) {
+	fail_face = "\033[41m\033[37m\033[1m";
+	normal_face = "\033[m";
+    }
+#endif
+
+    srcdir = getenv ("srcdir");
+    if (!srcdir)
+	srcdir = ".";
+
     if ((tname = getenv ("CAIRO_TEST_TARGET")) != NULL) {
 	const char *tname = getenv ("CAIRO_TEST_TARGET");
 	num_targets = 0;
@@ -1794,7 +1822,7 @@ cairo_test_expecting (cairo_test_t *test
      * iff. there is at least one tested backend and that all tested
      * backends return SUCCESS. In other words:
      *
-     *	if      any backend FAILURE
+     *	if      any backend not SUCCESS
      *		-> FAILURE
      *	else if all backends UNTESTED
      *		-> FAILURE
@@ -1812,7 +1840,13 @@ cairo_test_expecting (cairo_test_t *test
 		    _cairo_test_content_name (target->content),
 		    dev_offset);
 
-	    status = cairo_test_for_target (test, draw, target, dev_offset);
+	    /* Set up a checkpoint to get back to in case of segfaults. */
+	    old_segfault_handler = signal (SIGSEGV, (sighandler_t) segfault_handler);
+	    if (0 == setjmp (jmpbuf))
+		status = cairo_test_for_target (test, draw, target, dev_offset);
+	    else
+	        status = CAIRO_TEST_CRASHED;
+	    signal (SIGSEGV, (sighandler_t) old_segfault_handler);
 
 	    cairo_test_log ("TEST: %s TARGET: %s FORMAT: %s OFFSET: %d RESULT: ",
 			    test->name, target->name,
@@ -1830,6 +1864,11 @@ cairo_test_expecting (cairo_test_t *test
 		printf ("UNTESTED\n");
 		cairo_test_log ("UNTESTED\n");
 		break;
+	    case CAIRO_TEST_CRASHED:
+		printf ("%s!!!CRASHED!!!%s\n", fail_face, normal_face);
+		cairo_test_log ("CRASHED\n");
+		ret = CAIRO_TEST_FAILURE;
+		break;
 	    default:
 	    case CAIRO_TEST_FAILURE:
 		if (expectation == CAIRO_TEST_FAILURE) {
@@ -1870,12 +1909,6 @@ cairo_test_expect_failure (cairo_test_t	
 cairo_test_status_t
 cairo_test (cairo_test_t *test, cairo_test_draw_function_t draw)
 {
-#ifdef HAVE_UNISTD_H
-    if (isatty (1)) {
-	fail_face = "\033[41m\033[37m\033[1m";
-	normal_face = "\033[m";
-    }
-#endif
     printf ("\n");
     return cairo_test_expecting (test, draw, CAIRO_TEST_SUCCESS);
 }
diff --git a/test/cairo-test.h b/test/cairo-test.h
index d47c47f..f33ea1e 100644
--- a/test/cairo-test.h
+++ b/test/cairo-test.h
@@ -67,7 +67,8 @@ typedef unsigned __int64 uint64_t;
 typedef enum cairo_test_status {
     CAIRO_TEST_SUCCESS = 0,
     CAIRO_TEST_FAILURE,
-    CAIRO_TEST_UNTESTED
+    CAIRO_TEST_UNTESTED,
+    CAIRO_TEST_CRASHED
 } cairo_test_status_t;
 
 typedef struct cairo_test {


More information about the cairo-commit mailing list