[cairo-commit] 2 commits - test/cairo-test.c test/dash-infinite-loop.c test/dash-infinite-loop.ref.png test/Makefile.am test/Makefile.sources

Chris Wilson ickle at kemper.freedesktop.org
Tue Jul 28 00:43:14 PDT 2009


 test/Makefile.am                |    1 
 test/Makefile.sources           |    1 
 test/cairo-test.c               |   14 ++++--
 test/dash-infinite-loop.c       |   83 ++++++++++++++++++++++++++++++++++++++++
 test/dash-infinite-loop.ref.png |binary
 5 files changed, 95 insertions(+), 4 deletions(-)

New commits:
commit 24b5ac6377f0e4b76b73460a497b9861fc01a889
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Jul 28 08:05:22 2009 +0100

    [test] Add timeouts around finishing and converting surfaces to images.
    
    In order to catch infinite loops whilst replaying and converting vector
    surfaces to images (via external renderers) we need to also install
    alarms around the calls to finish() and get_image().

diff --git a/test/cairo-test.c b/test/cairo-test.c
index 430acc1..67323b5 100644
--- a/test/cairo-test.c
+++ b/test/cairo-test.c
@@ -90,6 +90,10 @@
 #define ARRAY_SIZE(A) (sizeof(A) / sizeof (A[0]))
 #endif
 
+#if ! HAVE_ALARM
+#define alarm(X);
+#endif
+
 static const cairo_user_data_key_t _cairo_test_context_key;
 
 static void
@@ -955,13 +959,9 @@ REPEAT:
     cairo_font_options_destroy (font_options);
 
     cairo_save (cr);
-#if HAVE_ALARM
     alarm (ctx->timeout);
-#endif
     status = (ctx->test->draw) (cr, ctx->test->width, ctx->test->height);
-#if HAVE_ALARM
     alarm (0);
-#endif
     cairo_restore (cr);
 
     if (similar) {
@@ -1040,7 +1040,10 @@ REPEAT:
 	    MEMFAULT_ENABLE_FAULTS ();
 #endif
 
+	    /* also check for infinite loops whilst replaying */
+	    alarm (ctx->timeout);
 	    diff_status = target->finish_surface (surface);
+	    alarm (0);
 
 #if HAVE_MEMFAULT
 	    MEMFAULT_DISABLE_FAULTS ();
@@ -1081,9 +1084,12 @@ REPEAT:
 
 	    /* we may be running this test to generate reference images */
 	    _xunlink (ctx, out_png_path);
+	    /* be more generous as we may need to use external renderers */
+	    alarm (4 * ctx->timeout);
 	    test_image = target->get_image_surface (surface, 0,
 		                                    ctx->test->width,
 						    ctx->test->height);
+	    alarm (0);
 	    diff_status = cairo_surface_write_to_png (test_image, out_png_path);
 	    cairo_surface_destroy (test_image);
 	    if (diff_status) {
commit dacc380dd9ea23fe060d0397104ecd4b2a6d0eae
Author: M Joonas Pihlaja <jpihlaja at cc.helsinki.fi>
Date:   Sat Jul 11 02:59:12 2009 +0300

    [test] Test extremely small dash lengths.
    
    The stroker code is liable to wedge when passed
    dash patterns which don't advance the dash offset
    due to limited precision arithmetic.  This test
    attempts to hit all the places in the stroker where
    that can happen.
    
    Reported on the cairo mailing list by Hans Breuer:
    
    http://lists.cairographics.org/archives/cairo/2009-June/017506.html

diff --git a/test/Makefile.am b/test/Makefile.am
index 7e42789..7a04e5e 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -269,6 +269,7 @@ REFERENCE_IMAGES = \
 	dash-curve.ps3.ref.png \
 	dash-curve.quartz.ref.png \
 	dash-curve.ref.png \
+	dash-infinite-loop.ref.png \
 	dash-no-dash.ref.png \
 	dash-offset-negative.ref.png \
 	dash-scale.ps2.argb32.ref.png \
diff --git a/test/Makefile.sources b/test/Makefile.sources
index 3acc255..ec7be36 100644
--- a/test/Makefile.sources
+++ b/test/Makefile.sources
@@ -38,6 +38,7 @@ test_sources = \
 	curve-to-as-line-to.c				\
 	dash-caps-joins.c				\
 	dash-curve.c					\
+	dash-infinite-loop.c				\
 	dash-no-dash.c					\
 	dash-offset-negative.c				\
 	dash-scale.c					\
diff --git a/test/dash-infinite-loop.c b/test/dash-infinite-loop.c
new file mode 100644
index 0000000..a3d7544
--- /dev/null
+++ b/test/dash-infinite-loop.c
@@ -0,0 +1,83 @@
+/*
+ * Copyright © 2009 M Joonas Pihlaja
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Author: M Joonas Pihlaja <jpihlaja at cc.helsinki.fi>
+ */
+
+#include "cairo-test.h"
+
+/* When faced with very small dash lengths the stroker is liable to
+ * get stuck in an infinite loop when advancing the dash offset.  This
+ * test attempts to hit each of the locations in the stroker code
+ * where the dash offset is advanced in a loop.
+ *
+ * Reported to the cairo mailing list by Hans Breuer.
+ * http://lists.cairographics.org/archives/cairo/2009-June/017506.html
+ */
+
+#define EPS 1e-30
+/* This should be comfortably smaller than the unit epsilon of the
+ * floating point type used to advance the dashing, yet not small
+ * enough that it underflows to zero.  1e-30 works to foil up to 80
+ * bit extended precision arithmetic.  We want to avoid zero dash
+ * lengths because those trigger special processing in the stroker. */
+
+static void
+do_dash (cairo_t *cr, double dx, double dy, double offset)
+{
+    /* Set the dash pattern to be predominantly ON so that we can
+     * create a reference image by just ignoring the dashing. */
+    static double dash[] = { EPS, EPS/512 };
+    cairo_set_dash (cr, dash, 2, offset);
+    cairo_move_to (cr, 10, 10);
+    cairo_rel_line_to (cr, dx, dy);
+    cairo_stroke (cr);
+    cairo_translate (cr, dx, dy);
+}
+
+static cairo_test_status_t
+draw (cairo_t *cr, int width, int height)
+{
+    (void)width; (void)height;
+
+    cairo_set_source_rgb (cr, 1,1,1);
+    cairo_paint (cr);
+    cairo_set_source_rgb (cr, 0,0,0);
+
+    cairo_set_line_width (cr, 10);
+
+    /* The following calls will wedge in various places that try
+     * to advance the dashing in a loop inside the stroker. */
+    do_dash (cr, 30, 30, 0); /* _cairo_stroker_line_to_dashed */
+    do_dash (cr, 30,  0, 0); /* _cairo_rectilinear_stroker_line_to_dashed */
+    do_dash (cr, 30, 30, 1); /* _cairo_stroker_dash_start */
+
+    return CAIRO_TEST_SUCCESS;
+}
+
+CAIRO_TEST (dash_infinite_loop,
+            "Test dashing with extremely small dash lengths.",
+            "dash",
+            NULL,
+            100, 100,
+            NULL, draw);
diff --git a/test/dash-infinite-loop.ref.png b/test/dash-infinite-loop.ref.png
new file mode 100644
index 0000000..c0cc739
Binary files /dev/null and b/test/dash-infinite-loop.ref.png differ


More information about the cairo-commit mailing list