[cairo-commit] 3 commits - boilerplate/cairo-boilerplate.c boilerplate/cairo-boilerplate.h build/configure.ac.noversion build/configure.ac.system build/configure.ac.version configure.ac doc/public Makefile.am src/cairo-type3-glyph-surface.c src/cairo-xlib-surface.c test/a1-image-sample.c test/a1-mask.c test/a1-traps-sample.c test/a8-mask.c test/alpha-similar.c test/big-line.c test/big-trap.c test/bilevel-image.c test/bitmap-font.c test/cairo-test.c test/cairo-test.h test/cairo-test-private.h test/cairo-test-runner.c test/caps-joins-alpha.c test/caps-joins.c test/caps-sub-paths.c test/clip-all.c test/clip-empty.c test/clip-fill-rule.c test/clip-fill-rule-pixel-aligned.c test/clip-nesting.c test/clip-operator.c test/clipped-group.c test/clipped-surface.c test/clip-push-group.c test/clip-twice.c test/clip-zero.c test/close-path.c test/composite-integer-translate-over.c test/composite-integer-translate-over-repeat.c test/composite-integer-translate-source.c test/copy-path.c test/create-for-stream.c test/create-from-png.c test/create-from-png-stream.c test/dash-caps-joins.c test/dash-curve.c test/dash-no-dash.c test/dash-offset-negative.c test/dash-scale.c test/dash-state.c test/dash-zero-length.c test/degenerate-arc.c test/degenerate-dash.c test/degenerate-path.c test/degenerate-pen.c test/device-offset.c test/device-offset-fractional.c test/device-offset-positive.c test/device-offset-scale.c test/extend-pad.c test/extend-reflect.c test/extend-reflect-similar.c test/extend-repeat.c test/extend-repeat-similar.c test/fallback-resolution.c test/fill-alpha.c test/fill-alpha-pattern.c test/fill-and-stroke-alpha-add.c test/fill-and-stroke-alpha.c test/fill-and-stroke.c test/fill-degenerate-sort-order.c test/fill-missed-stop.c test/fill-rule.c test/filter-bilinear-extents.c test/filter-nearest-offset.c test/filter-nearest-transformed.c test/finer-grained-fallbacks.c test/font-face-get-type.c test/font-matrix-translation.c test/font-options.c test/ft-font-create-for-ft-face.c test/ft-show-glyphs-positioning.c test/ft-show-glyphs-table.c test/ft-text-antialias-none.c test/ft-text-vertical-layout-type1.c test/ft-text-vertical-layout-type3.c test/get-and-set.c test/get-clip.c test/get-group-target.c test/get-path-extents.c test/get-xrender-format.c test/.gitignore test/glyph-cache-pressure.c test/gradient-alpha.c test/gradient-constant-alpha.c test/gradient-zero-stops.c test/group-paint.c test/huge-pattern.c test/image-surface-source.c test/in-fill-empty-trapezoid.c test/in-fill-trapezoid.c test/infinite-join.c test/invalid-matrix.c test/large-clip.c test/large-font.c test/large-source.c test/leaky-dash.c test/leaky-dashed-rectangle.c test/leaky-dashed-stroke.c test/leaky-polygon.c test/linear-gradient.c test/linear-gradient-reflect.c test/line-width.c test/line-width-scale.c test/line-width-zero.c test/long-dashed-lines.c test/long-lines.c test/make-cairo-test-constructors.pl test/Makefile.am test/mask-alpha.c test/mask.c test/mask-ctm.c test/mask-surface-ctm.c test/mask-transformed-image.c test/mask-transformed-similar.c test/meta-surface-pattern.c test/miter-precision.c test/move-to-show-surface.c test/multi-page.c test/new-sub-path.c test/nil-surface.c test/operator-alpha.c test/operator.c test/operator-clear.c test/operator-source.c test/over-above-source.c test/over-around-source.c test/over-below-source.c test/over-between-source.c test/paint.c test/paint-repeat.c test/paint-source-alpha.c test/paint-with-alpha.c test/pattern-getters.c test/pattern-get-type.c test/pdf-features.c test/pdf-surface-source.c test/pixman-rotate.c test/png.c test/ps-features.c test/ps-surface-source.c test/pthread-show-text.c test/push-group.c test/radial-gradient.c test/random-intersections.c test/README test/rectangle-rounding-error.c test/rectilinear-fill.c test/rectilinear-miter-limit.c test/rectilinear-stroke.c test/reflected-stroke.c test/rel-path.c test/rgb24-ignore-alpha.c test/rotate-image-surface-paint.c test/scale-down-source-surface-paint.c test/scale-source-surface-paint.c test/select-font-face.c test/select-font-no-show-text.c test/self-copy.c test/self-copy-overlap.c test/self-intersecting.c test/set-source.c test/show-glyphs-many.c test/show-text-current-point.c test/skew-extreme.c test/smask.c test/smask-fill.c test/smask-image-mask.c test/smask-mask.c test/smask-paint.c test/smask-stroke.c test/smask-text.c test/solid-pattern-cache-stress.c test/source-clip.c test/source-clip-scale.c test/source-surface-scale-paint.c test/spline-decomposition.c test/stroke-ctm-caps.c test/stroke-image.c test/surface-finish-twice.c test/surface-pattern-big-scale-down.c test/surface-pattern.c test/surface-pattern-scale-down.c test/surface-pattern-scale-down-pdf-rgb24-ref.png test/surface-pattern-scale-up.c test/surface-source.c test/svg-clip.c test/svg-surface.c test/svg-surface-source.c test/text-antialias-gray.c test/text-antialias-none.c test/text-antialias-subpixel.c test/text-cache-crash.c test/text-glyph-range.c test/text-glyph-range-ps2-ref.png test/text-glyph-range-ps3-ref.png test/text-glyph-range-ref.png test/text-glyph-range-rgb24-ref.png test/text-pattern.c test/text-rotate.c test/text-transform.c test/text-zero-len.c test/toy-font-face.c test/transforms.c test/translate-show-surface.c test/trap-clip.c test/truetype-tables.c test/twin.c test/unantialiased-shapes.c test/unbounded-operator.c test/user-data.c test/user-font.c test/user-font-mask.c test/user-font-proxy.c test/user-font-rescale.c test/xlib-expose-event.c test/xlib-surface.c test/xlib-surface-source.c test/zero-alpha.c

Chris Wilson ickle at kemper.freedesktop.org
Fri Oct 31 05:31:14 PDT 2008


 Makefile.am                                       |    1 
 boilerplate/cairo-boilerplate.c                   |  658 +++++++++------
 boilerplate/cairo-boilerplate.h                   |    1 
 build/configure.ac.noversion                      |   12 
 build/configure.ac.system                         |   57 +
 build/configure.ac.version                        |    8 
 configure.ac                                      |   16 
 dev/null                                          |binary
 doc/public/tmpl/cairo-surface.sgml                |    1 
 src/cairo-type3-glyph-surface.c                   |    3 
 src/cairo-xlib-surface.c                          |    1 
 test/.gitignore                                   |  237 -----
 test/Makefile.am                                  |  572 ++++++-------
 test/README                                       |   28 
 test/a1-image-sample.c                            |   20 
 test/a1-mask.c                                    |   38 
 test/a1-traps-sample.c                            |   20 
 test/a8-mask.c                                    |   37 
 test/alpha-similar.c                              |   23 
 test/big-line.c                                   |   22 
 test/big-trap.c                                   |   22 
 test/bilevel-image.c                              |   20 
 test/bitmap-font.c                                |   22 
 test/cairo-test-private.h                         |   74 +
 test/cairo-test-runner.c                          |  907 ++++++++++++++++++++++
 test/cairo-test.c                                 |  594 ++++++++------
 test/cairo-test.h                                 |   99 +-
 test/caps-joins-alpha.c                           |   26 
 test/caps-joins.c                                 |   27 
 test/caps-sub-paths.c                             |   21 
 test/clip-all.c                                   |   21 
 test/clip-empty.c                                 |   20 
 test/clip-fill-rule-pixel-aligned.c               |   22 
 test/clip-fill-rule.c                             |   20 
 test/clip-nesting.c                               |   20 
 test/clip-operator.c                              |   21 
 test/clip-push-group.c                            |   20 
 test/clip-twice.c                                 |   20 
 test/clip-zero.c                                  |   20 
 test/clipped-group.c                              |   20 
 test/clipped-surface.c                            |   19 
 test/close-path.c                                 |   18 
 test/composite-integer-translate-over-repeat.c    |   20 
 test/composite-integer-translate-over.c           |   22 
 test/composite-integer-translate-source.c         |   22 
 test/copy-path.c                                  |   33 
 test/create-for-stream.c                          |   53 -
 test/create-from-png-stream.c                     |   20 
 test/create-from-png.c                            |   82 -
 test/dash-caps-joins.c                            |   26 
 test/dash-curve.c                                 |   20 
 test/dash-no-dash.c                               |   20 
 test/dash-offset-negative.c                       |   20 
 test/dash-scale.c                                 |   26 
 test/dash-state.c                                 |   22 
 test/dash-zero-length.c                           |   20 
 test/degenerate-arc.c                             |   20 
 test/degenerate-dash.c                            |   20 
 test/degenerate-path.c                            |   21 
 test/degenerate-pen.c                             |   20 
 test/device-offset-fractional.c                   |   20 
 test/device-offset-positive.c                     |   20 
 test/device-offset-scale.c                        |   21 
 test/device-offset.c                              |   20 
 test/extend-pad.c                                 |   20 
 test/extend-reflect-similar.c                     |   22 
 test/extend-reflect.c                             |   22 
 test/extend-repeat-similar.c                      |   22 
 test/extend-repeat.c                              |   22 
 test/fallback-resolution.c                        |   28 
 test/fill-alpha-pattern.c                         |   20 
 test/fill-alpha.c                                 |   20 
 test/fill-and-stroke-alpha-add.c                  |   20 
 test/fill-and-stroke-alpha.c                      |   20 
 test/fill-and-stroke.c                            |   20 
 test/fill-degenerate-sort-order.c                 |   20 
 test/fill-missed-stop.c                           |   19 
 test/fill-rule.c                                  |   20 
 test/filter-bilinear-extents.c                    |   22 
 test/filter-nearest-offset.c                      |   21 
 test/filter-nearest-transformed.c                 |   19 
 test/finer-grained-fallbacks.c                    |   20 
 test/font-face-get-type.c                         |   28 
 test/font-matrix-translation.c                    |   20 
 test/font-options.c                               |   17 
 test/ft-font-create-for-ft-face.c                 |   21 
 test/ft-show-glyphs-positioning.c                 |   20 
 test/ft-show-glyphs-table.c                       |   21 
 test/ft-text-antialias-none.c                     |   20 
 test/ft-text-vertical-layout-type1.c              |   23 
 test/ft-text-vertical-layout-type3.c              |   20 
 test/get-and-set.c                                |   20 
 test/get-clip.c                                   |   21 
 test/get-group-target.c                           |   20 
 test/get-path-extents.c                           |   20 
 test/get-xrender-format.c                         |   35 
 test/glyph-cache-pressure.c                       |   20 
 test/gradient-alpha.c                             |   20 
 test/gradient-constant-alpha.c                    |   20 
 test/gradient-zero-stops.c                        |   22 
 test/group-paint.c                                |   20 
 test/huge-pattern.c                               |   21 
 test/image-surface-source.c                       |    8 
 test/in-fill-empty-trapezoid.c                    |   24 
 test/in-fill-trapezoid.c                          |   20 
 test/infinite-join.c                              |   22 
 test/invalid-matrix.c                             |   20 
 test/large-clip.c                                 |   22 
 test/large-font.c                                 |   22 
 test/large-source.c                               |   20 
 test/leaky-dash.c                                 |   22 
 test/leaky-dashed-rectangle.c                     |   20 
 test/leaky-dashed-stroke.c                        |   20 
 test/leaky-polygon.c                              |   20 
 test/line-width-scale.c                           |   20 
 test/line-width-zero.c                            |   20 
 test/line-width.c                                 |   20 
 test/linear-gradient-reflect.c                    |   21 
 test/linear-gradient.c                            |   20 
 test/long-dashed-lines.c                          |   20 
 test/long-lines.c                                 |   24 
 test/make-cairo-test-constructors.pl              |   18 
 test/mask-alpha.c                                 |   20 
 test/mask-ctm.c                                   |   21 
 test/mask-surface-ctm.c                           |   20 
 test/mask-transformed-image.c                     |   19 
 test/mask-transformed-similar.c                   |   19 
 test/mask.c                                       |   23 
 test/meta-surface-pattern.c                       |   20 
 test/miter-precision.c                            |   22 
 test/move-to-show-surface.c                       |   20 
 test/multi-page.c                                 |   30 
 test/new-sub-path.c                               |   22 
 test/nil-surface.c                                |   20 
 test/operator-alpha.c                             |   21 
 test/operator-clear.c                             |   20 
 test/operator-source.c                            |   20 
 test/operator.c                                   |   21 
 test/over-above-source.c                          |   20 
 test/over-around-source.c                         |   20 
 test/over-below-source.c                          |   20 
 test/over-between-source.c                        |   20 
 test/paint-repeat.c                               |   20 
 test/paint-source-alpha.c                         |   20 
 test/paint-with-alpha.c                           |   20 
 test/paint.c                                      |   20 
 test/pattern-get-type.c                           |   21 
 test/pattern-getters.c                            |   20 
 test/pdf-features.c                               |   31 
 test/pdf-surface-source.c                         |   10 
 test/pixman-rotate.c                              |   20 
 test/png.c                                        |   56 -
 test/ps-features.c                                |   29 
 test/ps-surface-source.c                          |   10 
 test/pthread-show-text.c                          |   41 
 test/push-group.c                                 |   20 
 test/radial-gradient.c                            |   22 
 test/random-intersections.c                       |   21 
 test/rectangle-rounding-error.c                   |   22 
 test/rectilinear-fill.c                           |   20 
 test/rectilinear-miter-limit.c                    |   20 
 test/rectilinear-stroke.c                         |   21 
 test/reflected-stroke.c                           |   21 
 test/rel-path.c                                   |   20 
 test/rgb24-ignore-alpha.c                         |   20 
 test/rotate-image-surface-paint.c                 |   22 
 test/scale-down-source-surface-paint.c            |   20 
 test/scale-source-surface-paint.c                 |   20 
 test/select-font-face.c                           |   28 
 test/select-font-no-show-text.c                   |   20 
 test/self-copy-overlap.c                          |   22 
 test/self-copy.c                                  |   20 
 test/self-intersecting.c                          |   22 
 test/set-source.c                                 |   20 
 test/show-glyphs-many.c                           |   20 
 test/show-text-current-point.c                    |   22 
 test/skew-extreme.c                               |   20 
 test/smask-fill.c                                 |   20 
 test/smask-image-mask.c                           |   20 
 test/smask-mask.c                                 |   20 
 test/smask-paint.c                                |   20 
 test/smask-stroke.c                               |   20 
 test/smask-text.c                                 |   20 
 test/smask.c                                      |   20 
 test/solid-pattern-cache-stress.c                 |   20 
 test/source-clip-scale.c                          |   20 
 test/source-clip.c                                |   20 
 test/source-surface-scale-paint.c                 |   20 
 test/spline-decomposition.c                       |   20 
 test/stroke-ctm-caps.c                            |   20 
 test/stroke-image.c                               |   20 
 test/surface-finish-twice.c                       |   20 
 test/surface-pattern-big-scale-down.c             |   20 
 test/surface-pattern-scale-down-pdf-rgb24-ref.png |binary
 test/surface-pattern-scale-down.c                 |   21 
 test/surface-pattern-scale-up.c                   |   21 
 test/surface-pattern.c                            |   24 
 test/surface-source.c                             |   15 
 test/svg-clip.c                                   |   26 
 test/svg-surface-source.c                         |   11 
 test/svg-surface.c                                |   26 
 test/text-antialias-gray.c                        |   20 
 test/text-antialias-none.c                        |   20 
 test/text-antialias-subpixel.c                    |   20 
 test/text-cache-crash.c                           |   40 
 test/text-glyph-range-ps2-ref.png                 |binary
 test/text-glyph-range-ps3-ref.png                 |binary
 test/text-glyph-range-ref.png                     |binary
 test/text-glyph-range.c                           |   62 -
 test/text-pattern.c                               |   54 -
 test/text-rotate.c                                |   22 
 test/text-transform.c                             |   22 
 test/text-zero-len.c                              |   20 
 test/toy-font-face.c                              |   16 
 test/transforms.c                                 |   20 
 test/translate-show-surface.c                     |   20 
 test/trap-clip.c                                  |   22 
 test/truetype-tables.c                            |   18 
 test/twin.c                                       |   20 
 test/unantialiased-shapes.c                       |   20 
 test/unbounded-operator.c                         |   20 
 test/user-data.c                                  |   17 
 test/user-font-mask.c                             |   28 
 test/user-font-proxy.c                            |   28 
 test/user-font-rescale.c                          |   20 
 test/user-font.c                                  |   28 
 test/xlib-expose-event.c                          |   28 
 test/xlib-surface-source.c                        |    8 
 test/xlib-surface.c                               |   36 
 test/zero-alpha.c                                 |   20 
 230 files changed, 3773 insertions(+), 4124 deletions(-)

New commits:
commit e90073f7ddc6f461a935bc360c409b04f1fe9f74
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Sep 3 16:38:03 2008 +0100

    [test] Build test suite into single binary.
    
    Avoid calling libtool to link every single test case, by building just one
    binary from all the sources.
    
    This binary is then given the task of choosing tests to run (based on user
    selection and individual test requirement), forking each test into its own
    process and accumulating the results.

diff --git a/Makefile.am b/Makefile.am
index 223ceec..5e6c89c 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -74,6 +74,7 @@ MAINTAINERCLEANFILES += \
 DISTCHECK_CONFIGURE_FLAGS = \
 	--enable-gtk-doc \
 	--enable-test-surfaces \
+	--enable-full-testing \
 	$(NULL)
 
 include $(srcdir)/build/Makefile.am.changelog
diff --git a/boilerplate/cairo-boilerplate.c b/boilerplate/cairo-boilerplate.c
index c2fa911..632624f 100644
--- a/boilerplate/cairo-boilerplate.c
+++ b/boilerplate/cairo-boilerplate.c
@@ -271,240 +271,329 @@ static cairo_boilerplate_target_t targets[] =
     /* I'm uncompromising about leaving the image backend as 0
      * for tolerance. There shouldn't ever be anything that is out of
      * our control here. */
-    { "image", NULL, CAIRO_SURFACE_TYPE_IMAGE, CAIRO_CONTENT_COLOR_ALPHA, 0,
-      _cairo_boilerplate_image_create_surface, NULL,
-      NULL,
-      _cairo_boilerplate_get_image_surface,
-      cairo_surface_write_to_png },
-    { "image", NULL, CAIRO_SURFACE_TYPE_IMAGE, CAIRO_CONTENT_COLOR, 0,
-      _cairo_boilerplate_image_create_surface, NULL,
-      NULL,
-      _cairo_boilerplate_get_image_surface,
-      cairo_surface_write_to_png },
+    {
+	"image", "image", NULL,
+	CAIRO_SURFACE_TYPE_IMAGE, CAIRO_CONTENT_COLOR_ALPHA, 0,
+	_cairo_boilerplate_image_create_surface, NULL,
+	NULL,
+	_cairo_boilerplate_get_image_surface,
+	cairo_surface_write_to_png
+    },
+    {
+	"image", "image", NULL,
+	CAIRO_SURFACE_TYPE_IMAGE, CAIRO_CONTENT_COLOR, 0,
+	_cairo_boilerplate_image_create_surface, NULL,
+	NULL,
+	_cairo_boilerplate_get_image_surface,
+	cairo_surface_write_to_png
+    },
 #ifdef CAIRO_HAS_TEST_SURFACES
-    { "test-fallback", NULL, CAIRO_INTERNAL_SURFACE_TYPE_TEST_FALLBACK,
-      CAIRO_CONTENT_COLOR_ALPHA, 0,
-      _cairo_boilerplate_test_fallback_create_surface, NULL,
-      NULL,
-      _cairo_boilerplate_get_image_surface,
-      cairo_surface_write_to_png },
-    { "test-fallback", NULL, CAIRO_INTERNAL_SURFACE_TYPE_TEST_FALLBACK,
-      CAIRO_CONTENT_COLOR, 0,
-      _cairo_boilerplate_test_fallback_create_surface, NULL,
-      NULL,
-      _cairo_boilerplate_get_image_surface,
-      cairo_surface_write_to_png },
-    { "test-meta", NULL, CAIRO_INTERNAL_SURFACE_TYPE_TEST_META,
-      CAIRO_CONTENT_COLOR_ALPHA, 0,
-      _cairo_boilerplate_test_meta_create_surface, NULL,
-      NULL,
-      _cairo_boilerplate_get_image_surface,
-      cairo_surface_write_to_png },
-    { "test-meta", NULL, CAIRO_INTERNAL_SURFACE_TYPE_TEST_META,
-      CAIRO_CONTENT_COLOR, 0,
-      _cairo_boilerplate_test_meta_create_surface, NULL,
-      NULL,
-      _cairo_boilerplate_get_image_surface,
-      cairo_surface_write_to_png },
-    { "test-paginated", NULL, CAIRO_INTERNAL_SURFACE_TYPE_TEST_PAGINATED,
-      CAIRO_CONTENT_COLOR_ALPHA, 0,
-      _cairo_boilerplate_test_paginated_create_surface, NULL,
-      NULL,
-      _cairo_boilerplate_test_paginated_get_image_surface,
-      _cairo_boilerplate_test_paginated_surface_write_to_png,
-      _cairo_boilerplate_test_paginated_cleanup },
-    { "test-paginated", NULL, CAIRO_INTERNAL_SURFACE_TYPE_TEST_PAGINATED,
-      CAIRO_CONTENT_COLOR, 0,
-      _cairo_boilerplate_test_paginated_create_surface, NULL,
-      NULL,
-      _cairo_boilerplate_test_paginated_get_image_surface,
-      _cairo_boilerplate_test_paginated_surface_write_to_png,
-      _cairo_boilerplate_test_paginated_cleanup },
+    {
+	"test-fallback", "image", NULL,
+	CAIRO_INTERNAL_SURFACE_TYPE_TEST_FALLBACK,
+	CAIRO_CONTENT_COLOR_ALPHA, 0,
+	_cairo_boilerplate_test_fallback_create_surface, NULL,
+	NULL,
+	_cairo_boilerplate_get_image_surface,
+	cairo_surface_write_to_png
+    },
+    {
+	"test-fallback", "image", NULL,
+	CAIRO_INTERNAL_SURFACE_TYPE_TEST_FALLBACK,
+	CAIRO_CONTENT_COLOR, 0,
+	_cairo_boilerplate_test_fallback_create_surface, NULL,
+	NULL,
+	_cairo_boilerplate_get_image_surface,
+	cairo_surface_write_to_png
+    },
+    {
+	"test-meta", "image", NULL,
+	CAIRO_INTERNAL_SURFACE_TYPE_TEST_META,
+	CAIRO_CONTENT_COLOR_ALPHA, 0,
+	_cairo_boilerplate_test_meta_create_surface, NULL,
+	NULL,
+	_cairo_boilerplate_get_image_surface,
+	cairo_surface_write_to_png
+    },
+    {
+	"test-meta", "image", NULL,
+	CAIRO_INTERNAL_SURFACE_TYPE_TEST_META,
+	CAIRO_CONTENT_COLOR, 0,
+	_cairo_boilerplate_test_meta_create_surface, NULL,
+	NULL,
+	_cairo_boilerplate_get_image_surface,
+	cairo_surface_write_to_png
+    },
+    {
+	"test-paginated", "image", NULL,
+	CAIRO_INTERNAL_SURFACE_TYPE_TEST_PAGINATED,
+	CAIRO_CONTENT_COLOR_ALPHA, 0,
+	_cairo_boilerplate_test_paginated_create_surface, NULL,
+	NULL,
+	_cairo_boilerplate_test_paginated_get_image_surface,
+	_cairo_boilerplate_test_paginated_surface_write_to_png,
+	_cairo_boilerplate_test_paginated_cleanup
+    },
+    {
+	"test-paginated", "image", NULL,
+	CAIRO_INTERNAL_SURFACE_TYPE_TEST_PAGINATED,
+	CAIRO_CONTENT_COLOR, 0,
+	_cairo_boilerplate_test_paginated_create_surface, NULL,
+	NULL,
+	_cairo_boilerplate_test_paginated_get_image_surface,
+	_cairo_boilerplate_test_paginated_surface_write_to_png,
+	_cairo_boilerplate_test_paginated_cleanup
+    },
 #endif
 #ifdef CAIRO_HAS_GLITZ_SURFACE
 #if CAIRO_CAN_TEST_GLITZ_GLX_SURFACE
-    { "glitz-glx", NULL, CAIRO_SURFACE_TYPE_GLITZ,CAIRO_CONTENT_COLOR_ALPHA, 0,
-      _cairo_boilerplate_glitz_glx_create_surface, NULL,
-      NULL,
-      _cairo_boilerplate_get_image_surface,
-      cairo_surface_write_to_png,
-      _cairo_boilerplate_glitz_glx_cleanup },
-    { "glitz-glx", NULL, CAIRO_SURFACE_TYPE_GLITZ, CAIRO_CONTENT_COLOR, 0,
-      _cairo_boilerplate_glitz_glx_create_surface, NULL,
-      NULL,
-      _cairo_boilerplate_get_image_surface,
-      cairo_surface_write_to_png,
-      _cairo_boilerplate_glitz_glx_cleanup },
+    {
+	"glitz-glx", "glitz", NULL,
+	CAIRO_SURFACE_TYPE_GLITZ,CAIRO_CONTENT_COLOR_ALPHA, 0,
+	_cairo_boilerplate_glitz_glx_create_surface, NULL,
+	NULL,
+	_cairo_boilerplate_get_image_surface,
+	cairo_surface_write_to_png,
+	_cairo_boilerplate_glitz_glx_cleanup
+    },
+    {
+	"glitz-glx", "glitz", NULL,
+	CAIRO_SURFACE_TYPE_GLITZ, CAIRO_CONTENT_COLOR, 0,
+	_cairo_boilerplate_glitz_glx_create_surface, NULL,
+	NULL,
+	_cairo_boilerplate_get_image_surface,
+	cairo_surface_write_to_png,
+	_cairo_boilerplate_glitz_glx_cleanup
+    },
 #endif
 #if CAIRO_CAN_TEST_GLITZ_AGL_SURFACE
-    { "glitz-agl", NULL, CAIRO_SURFACE_TYPE_GLITZ, CAIRO_CONTENT_COLOR_ALPHA, 0,
-      _cairo_boilerplate_glitz_agl_create_surface, NULL,
-      NULL,
-      _cairo_boilerplate_get_image_surface,
-      cairo_surface_write_to_png,
-      _cairo_boilerplate_glitz_agl_cleanup },
-    { "glitz-agl", NULL, CAIRO_SURFACE_TYPE_GLITZ, CAIRO_CONTENT_COLOR, 0,
-      _cairo_boilerplate_glitz_agl_create_surface, NULL,
-      NULL,
-      _cairo_boilerplate_get_image_surface,
-      cairo_surface_write_to_png,
-      _cairo_boilerplate_glitz_agl_cleanup },
+    {
+	"glitz-agl", "glitz", NULL,
+	CAIRO_SURFACE_TYPE_GLITZ, CAIRO_CONTENT_COLOR_ALPHA, 0,
+	_cairo_boilerplate_glitz_agl_create_surface, NULL,
+	NULL,
+	_cairo_boilerplate_get_image_surface,
+	cairo_surface_write_to_png,
+	_cairo_boilerplate_glitz_agl_cleanup
+    },
+    {
+	"glitz-agl", "glitz", NULL,
+	CAIRO_SURFACE_TYPE_GLITZ, CAIRO_CONTENT_COLOR, 0,
+	_cairo_boilerplate_glitz_agl_create_surface, NULL,
+	NULL,
+	_cairo_boilerplate_get_image_surface,
+	cairo_surface_write_to_png,
+	_cairo_boilerplate_glitz_agl_cleanup
+    },
 #endif
 #if CAIRO_CAN_TEST_GLITZ_WGL_SURFACE
-    { "glitz-wgl", NULL, CAIRO_SURFACE_TYPE_GLITZ, CAIRO_CONTENT_COLOR_ALPHA, 0,
-      _cairo_boilerplate_glitz_wgl_create_surface, NULL,
-      NULL,
-      _cairo_boilerplate_get_image_surface,
-      cairo_surface_write_to_png,
-      _cairo_boilerplate_glitz_wgl_cleanup },
-    { "glitz-wgl", NULL, CAIRO_SURFACE_TYPE_GLITZ, CAIRO_CONTENT_COLOR, 0,
-      _cairo_boilerplate_glitz_wgl_create_surface, NULL,
-      NULL,
-      _cairo_boilerplate_get_image_surface,
-      cairo_surface_write_to_png,
-      _cairo_boilerplate_glitz_wgl_cleanup },
+    {
+	"glitz-wgl", "glitz", NULL,
+	CAIRO_SURFACE_TYPE_GLITZ, CAIRO_CONTENT_COLOR_ALPHA, 0,
+	_cairo_boilerplate_glitz_wgl_create_surface, NULL,
+	NULL,
+	_cairo_boilerplate_get_image_surface,
+	cairo_surface_write_to_png,
+	_cairo_boilerplate_glitz_wgl_cleanup
+    },
+    {
+	"glitz-wgl", "glitz", NULL,
+	CAIRO_SURFACE_TYPE_GLITZ, CAIRO_CONTENT_COLOR, 0,
+	_cairo_boilerplate_glitz_wgl_create_surface, NULL,
+	NULL,
+	_cairo_boilerplate_get_image_surface,
+	cairo_surface_write_to_png,
+	_cairo_boilerplate_glitz_wgl_cleanup
+    },
 #endif
 #endif /* CAIRO_HAS_GLITZ_SURFACE */
 #if CAIRO_HAS_QUARTZ_SURFACE
-    { "quartz", NULL, CAIRO_SURFACE_TYPE_QUARTZ, CAIRO_CONTENT_COLOR_ALPHA, 0,
-      _cairo_boilerplate_quartz_create_surface, NULL,
-      NULL,
-      _cairo_boilerplate_get_image_surface,
-      cairo_surface_write_to_png,
-      _cairo_boilerplate_quartz_cleanup },
-    { "quartz", NULL, CAIRO_SURFACE_TYPE_QUARTZ, CAIRO_CONTENT_COLOR, 0,
-      _cairo_boilerplate_quartz_create_surface, NULL,
-      NULL,
-      _cairo_boilerplate_get_image_surface,
-      cairo_surface_write_to_png,
-      _cairo_boilerplate_quartz_cleanup },
+    {
+	"quartz", "quartz", NULL,
+	CAIRO_SURFACE_TYPE_QUARTZ, CAIRO_CONTENT_COLOR_ALPHA, 0,
+	_cairo_boilerplate_quartz_create_surface, NULL,
+	NULL,
+	_cairo_boilerplate_get_image_surface,
+	cairo_surface_write_to_png,
+	_cairo_boilerplate_quartz_cleanup
+    },
+    {
+	"quartz", "quartz", NULL,
+	CAIRO_SURFACE_TYPE_QUARTZ, CAIRO_CONTENT_COLOR, 0,
+	_cairo_boilerplate_quartz_create_surface, NULL,
+	NULL,
+	_cairo_boilerplate_get_image_surface,
+	cairo_surface_write_to_png,
+	_cairo_boilerplate_quartz_cleanup
+    },
 #endif
 #if CAIRO_HAS_WIN32_SURFACE
-    { "win32", NULL, CAIRO_SURFACE_TYPE_WIN32, CAIRO_CONTENT_COLOR, 0,
-      _cairo_boilerplate_win32_create_surface, NULL,
-      NULL,
-      _cairo_boilerplate_get_image_surface,
-      cairo_surface_write_to_png },
+    {
+	"win32", "win32", NULL,
+	CAIRO_SURFACE_TYPE_WIN32, CAIRO_CONTENT_COLOR, 0,
+	_cairo_boilerplate_win32_create_surface, NULL,
+	NULL,
+	_cairo_boilerplate_get_image_surface,
+	cairo_surface_write_to_png
+    },
     /* Testing the win32 surface isn't interesting, since for
      * ARGB images it just chains to the image backend
      */
-    { "win32", NULL, CAIRO_SURFACE_TYPE_WIN32, CAIRO_CONTENT_COLOR_ALPHA, 0,
-      _cairo_boilerplate_win32_create_surface, NULL,
-      NULL,
-      _cairo_boilerplate_get_image_surface,
-      cairo_surface_write_to_png },
+    {
+	"win32", "win32", NULL,
+	CAIRO_SURFACE_TYPE_WIN32, CAIRO_CONTENT_COLOR_ALPHA, 0,
+	_cairo_boilerplate_win32_create_surface, NULL,
+	NULL,
+	_cairo_boilerplate_get_image_surface,
+	cairo_surface_write_to_png
+    },
 #if CAIRO_CAN_TEST_WIN32_PRINTING_SURFACE
-    { "win32-printing", ".ps", CAIRO_SURFACE_TYPE_WIN32_PRINTING,
-      CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED, 0,
-      _cairo_boilerplate_win32_printing_create_surface, NULL,
-      NULL,
-      _cairo_boilerplate_win32_printing_get_image_surface,
-      _cairo_boilerplate_win32_printing_surface_write_to_png,
-      _cairo_boilerplate_win32_printing_cleanup,
-      NULL, TRUE },
-    { "win32-printing", ".ps", CAIRO_INTERNAL_SURFACE_TYPE_META, CAIRO_CONTENT_COLOR, 0,
-      _cairo_boilerplate_win32_printing_create_surface, NULL,
-      NULL,
-      _cairo_boilerplate_win32_printing_get_image_surface,
-      _cairo_boilerplate_win32_printing_surface_write_to_png,
-      _cairo_boilerplate_win32_printing_cleanup,
-      NULL, TRUE },
+    {
+	"win32-printing", "win32", ".ps",
+	CAIRO_SURFACE_TYPE_WIN32_PRINTING,
+	CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED, 0,
+	_cairo_boilerplate_win32_printing_create_surface, NULL,
+	NULL,
+	_cairo_boilerplate_win32_printing_get_image_surface,
+	_cairo_boilerplate_win32_printing_surface_write_to_png,
+	_cairo_boilerplate_win32_printing_cleanup,
+	NULL, TRUE
+    },
+    {
+	"win32-printing", "win32"".ps",
+	CAIRO_INTERNAL_SURFACE_TYPE_META, CAIRO_CONTENT_COLOR, 0,
+	_cairo_boilerplate_win32_printing_create_surface, NULL,
+	NULL,
+	_cairo_boilerplate_win32_printing_get_image_surface,
+	_cairo_boilerplate_win32_printing_surface_write_to_png,
+	_cairo_boilerplate_win32_printing_cleanup,
+	NULL, TRUE
+    },
 #endif
 #endif
 #if CAIRO_HAS_XCB_SURFACE
     /* Acceleration architectures may make the results differ by a
      * bit, so we set the error tolerance to 1. */
-    { "xcb", NULL, CAIRO_SURFACE_TYPE_XCB, CAIRO_CONTENT_COLOR_ALPHA, 1,
-      _cairo_boilerplate_xcb_create_surface, NULL,
-      NULL,
-      _cairo_boilerplate_get_image_surface,
-      cairo_surface_write_to_png,
-      _cairo_boilerplate_xcb_cleanup,
-      _cairo_boilerplate_xcb_synchronize},
+    {
+	"xcb", "xcb", NULL,
+	CAIRO_SURFACE_TYPE_XCB, CAIRO_CONTENT_COLOR_ALPHA, 1,
+	_cairo_boilerplate_xcb_create_surface, NULL,
+	NULL,
+	_cairo_boilerplate_get_image_surface,
+	cairo_surface_write_to_png,
+	_cairo_boilerplate_xcb_cleanup,
+	_cairo_boilerplate_xcb_synchronize
+    },
 #endif
 #if CAIRO_HAS_XLIB_XRENDER_SURFACE
     /* Acceleration architectures may make the results differ by a
      * bit, so we set the error tolerance to 1. */
-    { "xlib", NULL, CAIRO_SURFACE_TYPE_XLIB, CAIRO_CONTENT_COLOR_ALPHA, 1,
-      _cairo_boilerplate_xlib_create_surface, NULL,
-      NULL,
-      _cairo_boilerplate_get_image_surface,
-      cairo_surface_write_to_png,
-      _cairo_boilerplate_xlib_cleanup,
-      _cairo_boilerplate_xlib_synchronize},
-    { "xlib", NULL, CAIRO_SURFACE_TYPE_XLIB, CAIRO_CONTENT_COLOR, 1,
-      _cairo_boilerplate_xlib_create_surface, NULL,
-      NULL,
-      _cairo_boilerplate_get_image_surface,
-      cairo_surface_write_to_png,
-      _cairo_boilerplate_xlib_cleanup,
-      _cairo_boilerplate_xlib_synchronize},
+    {
+	"xlib", "xlib", NULL,
+	CAIRO_SURFACE_TYPE_XLIB, CAIRO_CONTENT_COLOR_ALPHA, 1,
+	_cairo_boilerplate_xlib_create_surface, NULL,
+	NULL,
+	_cairo_boilerplate_get_image_surface,
+	cairo_surface_write_to_png,
+	_cairo_boilerplate_xlib_cleanup,
+	_cairo_boilerplate_xlib_synchronize
+    },
+    {
+	"xlib", "xlib", NULL, CAIRO_SURFACE_TYPE_XLIB, CAIRO_CONTENT_COLOR, 1,
+	_cairo_boilerplate_xlib_create_surface, NULL,
+	NULL,
+	_cairo_boilerplate_get_image_surface,
+	cairo_surface_write_to_png,
+	_cairo_boilerplate_xlib_cleanup,
+	_cairo_boilerplate_xlib_synchronize
+    },
 #endif
 #if CAIRO_HAS_XLIB_SURFACE
     /* This is a fallback surface which uses xlib fallbacks instead of
      * the Render extension. */
-    { "xlib-fallback", NULL, CAIRO_SURFACE_TYPE_XLIB, CAIRO_CONTENT_COLOR, 1,
-      _cairo_boilerplate_xlib_fallback_create_surface, NULL,
-      NULL,
-      _cairo_boilerplate_get_image_surface,
-      cairo_surface_write_to_png,
-      _cairo_boilerplate_xlib_cleanup,
-      _cairo_boilerplate_xlib_synchronize},
+    {
+	"xlib-fallback", "xlib", NULL,
+	CAIRO_SURFACE_TYPE_XLIB, CAIRO_CONTENT_COLOR, 1,
+	_cairo_boilerplate_xlib_fallback_create_surface, NULL,
+	NULL,
+	_cairo_boilerplate_get_image_surface,
+	cairo_surface_write_to_png,
+	_cairo_boilerplate_xlib_cleanup,
+	_cairo_boilerplate_xlib_synchronize
+    },
 #endif
 #if CAIRO_HAS_PS_SURFACE && CAIRO_CAN_TEST_PS_SURFACE
-    { "ps2", ".ps", CAIRO_SURFACE_TYPE_PS,
-      CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED, 0,
-      _cairo_boilerplate_ps2_create_surface,
-      _cairo_boilerplate_ps_force_fallbacks,
-      _cairo_boilerplate_ps_finish_surface,
-      _cairo_boilerplate_ps_get_image_surface,
-      _cairo_boilerplate_ps_surface_write_to_png,
-      _cairo_boilerplate_ps_cleanup,
-      NULL, TRUE },
-    { "ps2", ".ps", CAIRO_INTERNAL_SURFACE_TYPE_META, CAIRO_CONTENT_COLOR, 0,
-      _cairo_boilerplate_ps2_create_surface,
-      _cairo_boilerplate_ps_force_fallbacks,
-      _cairo_boilerplate_ps_finish_surface,
-      _cairo_boilerplate_ps_get_image_surface,
-      _cairo_boilerplate_ps_surface_write_to_png,
-      _cairo_boilerplate_ps_cleanup,
-      NULL, TRUE },
-    { "ps3", ".ps", CAIRO_SURFACE_TYPE_PS,
-      CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED, 0,
-      _cairo_boilerplate_ps3_create_surface,
-      _cairo_boilerplate_ps_force_fallbacks,
-      _cairo_boilerplate_ps_finish_surface,
-      _cairo_boilerplate_ps_get_image_surface,
-      _cairo_boilerplate_ps_surface_write_to_png,
-      _cairo_boilerplate_ps_cleanup,
-      NULL, TRUE },
-    { "ps3", ".ps", CAIRO_INTERNAL_SURFACE_TYPE_META, CAIRO_CONTENT_COLOR, 0,
-      _cairo_boilerplate_ps3_create_surface,
-      _cairo_boilerplate_ps_force_fallbacks,
-      _cairo_boilerplate_ps_finish_surface,
-      _cairo_boilerplate_ps_get_image_surface,
-      _cairo_boilerplate_ps_surface_write_to_png,
-      _cairo_boilerplate_ps_cleanup,
-      NULL, TRUE },
+    {
+	"ps2", "ps", ".ps",
+	CAIRO_SURFACE_TYPE_PS,
+	CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED, 0,
+	_cairo_boilerplate_ps2_create_surface,
+	_cairo_boilerplate_ps_force_fallbacks,
+	_cairo_boilerplate_ps_finish_surface,
+	_cairo_boilerplate_ps_get_image_surface,
+	_cairo_boilerplate_ps_surface_write_to_png,
+	_cairo_boilerplate_ps_cleanup,
+	NULL, TRUE
+    },
+    {
+	"ps2", "ps", ".ps",
+	CAIRO_INTERNAL_SURFACE_TYPE_META, CAIRO_CONTENT_COLOR, 0,
+	_cairo_boilerplate_ps2_create_surface,
+	_cairo_boilerplate_ps_force_fallbacks,
+	_cairo_boilerplate_ps_finish_surface,
+	_cairo_boilerplate_ps_get_image_surface,
+	_cairo_boilerplate_ps_surface_write_to_png,
+	_cairo_boilerplate_ps_cleanup,
+	NULL, TRUE
+    },
+    {
+	"ps3", "ps", ".ps",
+	CAIRO_SURFACE_TYPE_PS,
+	CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED, 0,
+	_cairo_boilerplate_ps3_create_surface,
+	_cairo_boilerplate_ps_force_fallbacks,
+	_cairo_boilerplate_ps_finish_surface,
+	_cairo_boilerplate_ps_get_image_surface,
+	_cairo_boilerplate_ps_surface_write_to_png,
+	_cairo_boilerplate_ps_cleanup,
+	NULL, TRUE
+    },
+    {
+	"ps3", "ps", ".ps",
+	CAIRO_INTERNAL_SURFACE_TYPE_META, CAIRO_CONTENT_COLOR, 0,
+	_cairo_boilerplate_ps3_create_surface,
+	_cairo_boilerplate_ps_force_fallbacks,
+	_cairo_boilerplate_ps_finish_surface,
+	_cairo_boilerplate_ps_get_image_surface,
+	_cairo_boilerplate_ps_surface_write_to_png,
+	_cairo_boilerplate_ps_cleanup,
+	NULL, TRUE
+    },
 #endif
 #if CAIRO_HAS_PDF_SURFACE && CAIRO_CAN_TEST_PDF_SURFACE
-    { "pdf", ".pdf", CAIRO_SURFACE_TYPE_PDF,
-      CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED, 0,
-      _cairo_boilerplate_pdf_create_surface,
-      _cairo_boilerplate_pdf_force_fallbacks,
-      _cairo_boilerplate_pdf_finish_surface,
-      _cairo_boilerplate_pdf_get_image_surface,
-      _cairo_boilerplate_pdf_surface_write_to_png,
-      _cairo_boilerplate_pdf_cleanup,
-      NULL, TRUE },
-    { "pdf", ".pdf", CAIRO_INTERNAL_SURFACE_TYPE_META, CAIRO_CONTENT_COLOR, 0,
-      _cairo_boilerplate_pdf_create_surface,
-      _cairo_boilerplate_pdf_force_fallbacks,
-      _cairo_boilerplate_pdf_finish_surface,
-      _cairo_boilerplate_pdf_get_image_surface,
-      _cairo_boilerplate_pdf_surface_write_to_png,
-      _cairo_boilerplate_pdf_cleanup,
-      NULL, TRUE },
+    {
+	"pdf", "pdf", ".pdf",
+	CAIRO_SURFACE_TYPE_PDF,
+	CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED, 0,
+	_cairo_boilerplate_pdf_create_surface,
+	_cairo_boilerplate_pdf_force_fallbacks,
+	_cairo_boilerplate_pdf_finish_surface,
+	_cairo_boilerplate_pdf_get_image_surface,
+	_cairo_boilerplate_pdf_surface_write_to_png,
+	_cairo_boilerplate_pdf_cleanup,
+	NULL, TRUE
+    },
+    {
+	"pdf", "pdf", ".pdf",
+	CAIRO_INTERNAL_SURFACE_TYPE_META, CAIRO_CONTENT_COLOR, 0,
+	_cairo_boilerplate_pdf_create_surface,
+	_cairo_boilerplate_pdf_force_fallbacks,
+	_cairo_boilerplate_pdf_finish_surface,
+	_cairo_boilerplate_pdf_get_image_surface,
+	_cairo_boilerplate_pdf_surface_write_to_png,
+	_cairo_boilerplate_pdf_cleanup,
+	NULL, TRUE
+    },
 #endif
 #if CAIRO_HAS_SVG_SURFACE && CAIRO_CAN_TEST_SVG_SURFACE
     /* It seems we should be able to round-trip SVG content perfectly
@@ -512,89 +601,114 @@ static cairo_boilerplate_target_t targets[] =
      * systems get an error of 1 for some pixels on some of the text
      * tests. XXX: I'd still like to chase these down at some point.
      * For now just set the svg error tolerance to 1. */
-    { "svg11", NULL, CAIRO_SURFACE_TYPE_SVG, CAIRO_CONTENT_COLOR_ALPHA, 1,
-      _cairo_boilerplate_svg11_create_surface,
-      _cairo_boilerplate_svg_force_fallbacks,
-      _cairo_boilerplate_svg_finish_surface,
-      _cairo_boilerplate_svg_get_image_surface,
-      _cairo_boilerplate_svg_surface_write_to_png,
-      _cairo_boilerplate_svg_cleanup,
-      NULL, TRUE },
-    { "svg11", NULL, CAIRO_INTERNAL_SURFACE_TYPE_META, CAIRO_CONTENT_COLOR, 1,
-      _cairo_boilerplate_svg11_create_surface,
-      _cairo_boilerplate_svg_force_fallbacks,
-      _cairo_boilerplate_svg_finish_surface,
-      _cairo_boilerplate_svg_get_image_surface,
-      _cairo_boilerplate_svg_surface_write_to_png,
-      _cairo_boilerplate_svg_cleanup,
-      NULL, TRUE },
-/* Disable the svg12 testing for the 1.8.2 release, but in a way that it
- * will come back on immediately afterward even if we forget to remove
- * this condition. */
-    { "svg12", NULL, CAIRO_SURFACE_TYPE_SVG, CAIRO_CONTENT_COLOR_ALPHA, 1,
-      _cairo_boilerplate_svg12_create_surface,
-      _cairo_boilerplate_svg_force_fallbacks,
-      _cairo_boilerplate_svg_finish_surface,
-      _cairo_boilerplate_svg_get_image_surface,
-      _cairo_boilerplate_svg_surface_write_to_png,
-      _cairo_boilerplate_svg_cleanup,
-      NULL, TRUE },
-    { "svg12", NULL, CAIRO_INTERNAL_SURFACE_TYPE_META, CAIRO_CONTENT_COLOR, 1,
-      _cairo_boilerplate_svg12_create_surface,
-      _cairo_boilerplate_svg_force_fallbacks,
-      _cairo_boilerplate_svg_finish_surface,
-      _cairo_boilerplate_svg_get_image_surface,
-      _cairo_boilerplate_svg_surface_write_to_png,
-      _cairo_boilerplate_svg_cleanup,
-      NULL, TRUE },
+    {
+	"svg11", "svg", NULL,
+	CAIRO_SURFACE_TYPE_SVG, CAIRO_CONTENT_COLOR_ALPHA, 1,
+	_cairo_boilerplate_svg11_create_surface,
+	_cairo_boilerplate_svg_force_fallbacks,
+	_cairo_boilerplate_svg_finish_surface,
+	_cairo_boilerplate_svg_get_image_surface,
+	_cairo_boilerplate_svg_surface_write_to_png,
+	_cairo_boilerplate_svg_cleanup,
+	NULL, TRUE
+    },
+    {
+	"svg11", "svg", NULL,
+	CAIRO_INTERNAL_SURFACE_TYPE_META, CAIRO_CONTENT_COLOR, 1,
+	_cairo_boilerplate_svg11_create_surface,
+	_cairo_boilerplate_svg_force_fallbacks,
+	_cairo_boilerplate_svg_finish_surface,
+	_cairo_boilerplate_svg_get_image_surface,
+	_cairo_boilerplate_svg_surface_write_to_png,
+	_cairo_boilerplate_svg_cleanup,
+	NULL, TRUE
+    },
+    {
+	"svg12", "svg", NULL,
+	CAIRO_SURFACE_TYPE_SVG, CAIRO_CONTENT_COLOR_ALPHA, 1,
+	_cairo_boilerplate_svg12_create_surface,
+	_cairo_boilerplate_svg_force_fallbacks,
+	_cairo_boilerplate_svg_finish_surface,
+	_cairo_boilerplate_svg_get_image_surface,
+	_cairo_boilerplate_svg_surface_write_to_png,
+	_cairo_boilerplate_svg_cleanup,
+	NULL, TRUE
+    },
+    {
+	"svg12", "svg", NULL,
+	CAIRO_INTERNAL_SURFACE_TYPE_META, CAIRO_CONTENT_COLOR, 1,
+	_cairo_boilerplate_svg12_create_surface,
+	_cairo_boilerplate_svg_force_fallbacks,
+	_cairo_boilerplate_svg_finish_surface,
+	_cairo_boilerplate_svg_get_image_surface,
+	_cairo_boilerplate_svg_surface_write_to_png,
+	_cairo_boilerplate_svg_cleanup,
+	NULL, TRUE
+    },
 #endif
 #if CAIRO_HAS_BEOS_SURFACE
     /* BeOS sometimes produces a slightly different image. Perhaps this
      * is related to the fact that it doesn't use premultiplied alpha...
      * Just ignore the small difference. */
-    { "beos", NULL, CAIRO_SURFACE_TYPE_BEOS, CAIRO_CONTENT_COLOR, 1,
-      _cairo_boilerplate_beos_create_surface, NULL,
-      NULL,
-      _cairo_boilerplate_get_image_surface,
-      cairo_surface_write_to_png,
-      _cairo_boilerplate_beos_cleanup},
-    { "beos-bitmap", NULL, CAIRO_SURFACE_TYPE_BEOS, CAIRO_CONTENT_COLOR, 1,
-      _cairo_boilerplate_beos_create_surface_for_bitmap, NULL,
-      NULL,
-      _cairo_boilerplate_get_image_surface,
-      cairo_surface_write_to_png,
-      _cairo_boilerplate_beos_cleanup_bitmap},
-    { "beos-bitmap", NULL, CAIRO_SURFACE_TYPE_BEOS, CAIRO_CONTENT_COLOR_ALPHA, 1,
-      _cairo_boilerplate_beos_create_surface_for_bitmap, NULL,
-      NULL,
-      _cairo_boilerplate_get_image_surface,
-      cairo_surface_write_to_png,
-      _cairo_boilerplate_beos_cleanup_bitmap},
+    {
+	"beos", "beos", NULL,
+	CAIRO_SURFACE_TYPE_BEOS, CAIRO_CONTENT_COLOR, 1,
+	_cairo_boilerplate_beos_create_surface, NULL,
+	NULL,
+	_cairo_boilerplate_get_image_surface,
+	cairo_surface_write_to_png,
+	_cairo_boilerplate_beos_cleanup
+    },
+    {
+	"beos-bitmap", "beos", NULL,
+	CAIRO_SURFACE_TYPE_BEOS, CAIRO_CONTENT_COLOR, 1,
+	_cairo_boilerplate_beos_create_surface_for_bitmap, NULL,
+	NULL,
+	_cairo_boilerplate_get_image_surface,
+	cairo_surface_write_to_png,
+	_cairo_boilerplate_beos_cleanup_bitmap
+    },
+    {
+	"beos-bitmap", "beos", NULL,
+	CAIRO_SURFACE_TYPE_BEOS, CAIRO_CONTENT_COLOR_ALPHA, 1,
+	_cairo_boilerplate_beos_create_surface_for_bitmap, NULL,
+	NULL,
+	_cairo_boilerplate_get_image_surface,
+	cairo_surface_write_to_png,
+	_cairo_boilerplate_beos_cleanup_bitmap
+    },
 #endif
 
-
 #if CAIRO_HAS_DIRECTFB_SURFACE
-    { "directfb", NULL, CAIRO_SURFACE_TYPE_DIRECTFB, CAIRO_CONTENT_COLOR, 0,
-      _cairo_boilerplate_directfb_create_surface, NULL,
-      NULL,
-      _cairo_boilerplate_get_image_surface,
-      cairo_surface_write_to_png,
-      _cairo_boilerplate_directfb_cleanup},
-    { "directfb-bitmap", NULL, CAIRO_SURFACE_TYPE_DIRECTFB, CAIRO_CONTENT_COLOR_ALPHA, 0,
-      _cairo_boilerplate_directfb_create_surface, NULL,
-      NULL,
-      _cairo_boilerplate_get_image_surface,
-      cairo_surface_write_to_png,
-      _cairo_boilerplate_directfb_cleanup},
+    {
+	"directfb", "directfb", NULL,
+	CAIRO_SURFACE_TYPE_DIRECTFB, CAIRO_CONTENT_COLOR, 0,
+	_cairo_boilerplate_directfb_create_surface, NULL,
+	NULL,
+	_cairo_boilerplate_get_image_surface,
+	cairo_surface_write_to_png,
+	_cairo_boilerplate_directfb_cleanup
+    },
+    {
+	"directfb-bitmap", "directfb", NULL,
+	CAIRO_SURFACE_TYPE_DIRECTFB, CAIRO_CONTENT_COLOR_ALPHA, 0,
+	_cairo_boilerplate_directfb_create_surface, NULL,
+	NULL,
+	_cairo_boilerplate_get_image_surface,
+	cairo_surface_write_to_png,
+	_cairo_boilerplate_directfb_cleanup
+    },
 #endif
 
 #if CAIRO_HAS_SDL_SURFACE
-    { "sdl", NULL, CAIRO_SURFACE_TYPE_SDL, CAIRO_CONTENT_COLOR, 0,
-      _cairo_boilerplate_sdl_create_surface, NULL,
-      NULL,
-      _cairo_boilerplate_get_image_surface,
-      cairo_surface_write_to_png,
-      _cairo_boilerplate_sdl_cleanup
+    {
+	"sdl", "sdl", NULL,
+	CAIRO_SURFACE_TYPE_SDL, CAIRO_CONTENT_COLOR, 0,
+	_cairo_boilerplate_sdl_create_surface, NULL,
+	NULL,
+	_cairo_boilerplate_get_image_surface,
+	cairo_surface_write_to_png,
+	_cairo_boilerplate_sdl_cleanup
     },
 #endif
 };
diff --git a/boilerplate/cairo-boilerplate.h b/boilerplate/cairo-boilerplate.h
index 11fb1c3..9d12b8d 100644
--- a/boilerplate/cairo-boilerplate.h
+++ b/boilerplate/cairo-boilerplate.h
@@ -149,6 +149,7 @@ typedef void
 typedef struct _cairo_boilerplate_target
 {
     const char					*name;
+    const char					*basename;
     const char					*file_extension;
     cairo_surface_type_t			 expected_type;
     cairo_content_t				 content;
diff --git a/build/configure.ac.noversion b/build/configure.ac.noversion
new file mode 100644
index 0000000..1e14548
--- /dev/null
+++ b/build/configure.ac.noversion
@@ -0,0 +1,12 @@
+dnl
+dnl Version stuff
+dnl
+
+dnl Disable autoconf's version macros.  We try hard to not rebuild the entire
+dnl library just because version changed.  The PACKAGE_VERSION* stuff in
+dnl config.h is negating all the effort.
+AC_DEFINE(PACKAGE_VERSION,	[USE_cairo_version_OR_cairo_version_string_INSTEAD])
+AC_DEFINE(PACKAGE_STRING,	[USE_cairo_version_OR_cairo_version_string_INSTEAD])
+AC_DEFINE(PACKAGE_NAME,		[USE_cairo_INSTEAD])
+AC_DEFINE(PACKAGE_TARNAME,	[USE_cairo_INSTEAD])
+
diff --git a/build/configure.ac.system b/build/configure.ac.system
index 2102627..e915443 100644
--- a/build/configure.ac.system
+++ b/build/configure.ac.system
@@ -72,3 +72,60 @@ AC_CHECK_FUNCS([vasnprintf link ctime_r drand48 flockfile])
 dnl check for win32 headers (this detects mingw as well)
 AC_CHECK_HEADERS([windows.h], have_windows=yes, have_windows=no)
 
+
+dnl Possible headers for mkdir
+AC_CHECK_HEADERS([sys/stat.h io.h])
+AC_CHECK_FUNC(mkdir,
+	      [AC_MSG_CHECKING([mkdir variant])
+	      mkdir_variant="unknown"
+	      save_CFLAGS="$CFLAGS"
+	      CFLAGS="-Werror -Wall $CFLAGS" # non-gcc compilers?
+	      AC_TRY_COMPILE([
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#ifdef HAVE_IO_H
+#include <io.h>
+#endif
+		      ],
+		      [mkdir ("hello.world", 0777)],
+		      mkdir_variant="mkdir(path, mode)",
+		      [AC_TRY_COMPILE([
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#ifdef HAVE_IO_H
+#include <io.h>
+#endif
+			      ],
+			      [mkdir ("hello.world")],
+			      mkdir_variant="mkdir(path)")])
+	      AC_MSG_RESULT([$mkdir_variant])
+	      CFLAGS="$save_CFLAGS"
+	      if test "x$mkdir_variant" = "xmkdir(path, mode)"; then
+		  AC_DEFINE(HAVE_MKDIR, 2,
+			    [Define to non-zero if your system has mkdir, and to 2 if your version of mkdir requires a mode parameter])
+	      else
+		  AC_DEFINE(HAVE_MKDIR, 1,
+			    [Define to non-zero if your system has mkdir, and to 2 if your version of mkdir requires a mode parameter])
+	      fi])
+
+# check for GNU-extensions to fenv
+AC_CHECK_HEADER(fenv.h, [AC_CHECK_FUNCS(feenableexcept fedisableexcept)])
+
+dnl ===========================================================================
+dnl
+dnl Test for the tools required for building one big test binary
+dnl
+AC_MSG_CHECKING([for the constructor attribute])
+cairo_has_constructor_attribute="no"
+AC_TRY_LINK([static void __attribute__((constructor)) constructor(void) {}], [],
+    cairo_has_constructor_attribute="yes"
+  )
+AC_MSG_RESULT([$cairo_has_constructor_attribute])
+if test "x$cairo_has_constructor_attribute" = "xyes"; then
+    AC_DEFINE(CAIRO_HAS_CONSTRUCTOR_ATTRIBUTE, 1, [Define to 1 if your compiler supports __attribute__(constructor)])
+fi
+AM_CONDITIONAL(CAIRO_HAS_CONSTRUCTOR_ATTRIBUTE, test "x$cairo_has_constructor_attribute" = "xyes")
+
+AC_CHECK_FUNCS(fork waitpid raise)
diff --git a/build/configure.ac.version b/build/configure.ac.version
index 31ba7f4..a91cee3 100644
--- a/build/configure.ac.version
+++ b/build/configure.ac.version
@@ -40,11 +40,3 @@ AC_SUBST(CAIRO_VERSION_MICRO)
 AC_SUBST(CAIRO_VERSION_SONUM)
 AC_SUBST(CAIRO_RELEASE_STATUS)
 AC_SUBST(CAIRO_LIBTOOL_VERSION_INFO)
-
-dnl Disable autoconf's version macros.  We try hard to not rebuild the entire
-dnl library just because version changed.  The PACKAGE_VERSION* stuff in
-dnl config.h is negating all the effort.
-AC_DEFINE(PACKAGE_VERSION,	[USE_cairo_version_OR_cairo_version_string_INSTEAD])
-AC_DEFINE(PACKAGE_STRING,	[USE_cairo_version_OR_cairo_version_string_INSTEAD])
-AC_DEFINE(PACKAGE_NAME,		[USE_cairo_INSTEAD])
-AC_DEFINE(PACKAGE_TARNAME,	[USE_cairo_INSTEAD])
diff --git a/configure.ac b/configure.ac
index e14e14c..a27a73a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -23,6 +23,7 @@ m4_include(build/configure.ac.system)	dnl checks for system functions, headers,
 m4_include(build/configure.ac.features)	dnl macros for backend/feature handling
 m4_include(build/configure.ac.warnings)	dnl checks for compiler warning
 m4_include(build/configure.ac.analysis)	dnl checks for analysis tools (lcov, etc)
+m4_include(build/configure.ac.noversion) dnl disable builtin libtool versioning
 AC_CACHE_SAVE
 
 dnl ===========================================================================
@@ -458,6 +459,21 @@ dnl ===========================================================================
 CAIRO_ENABLE_FONT_BACKEND(user, user, always)
 
 dnl ===========================================================================
+dnl Default to quick testing during development, but force a full test before
+dnl release
+
+AC_ARG_ENABLE(full-testing,
+  AS_HELP_STRING([--enable-full-testing],
+                 [Sets the test suite to perform full testing by default, which
+		  will dramatically slow down make check, but is a
+		  *requirement* before release.]), [
+if test "x$enableval" = "xyes"; then
+    CAIRO_TEST_MODE=full
+    AC_SUBST(CAIRO_TEST_MODE)
+fi
+])
+
+dnl ===========================================================================
 dnl Build the external converter if we have any of the test backends
 AM_CONDITIONAL(BUILD_ANY2PPM,
 	       test "x$any2ppm_svg" = "xyes" \
diff --git a/doc/public/tmpl/cairo-surface.sgml b/doc/public/tmpl/cairo-surface.sgml
index 6b6c2f4..3a6cd8d 100644
--- a/doc/public/tmpl/cairo-surface.sgml
+++ b/doc/public/tmpl/cairo-surface.sgml
@@ -193,6 +193,7 @@ cairo_<emphasis>backend</emphasis>_surface_create().
 @CAIRO_SURFACE_TYPE_OS2: 
 @CAIRO_SURFACE_TYPE_WIN32_PRINTING: 
 @CAIRO_SURFACE_TYPE_QUARTZ_IMAGE: 
+ at CAIRO_SURFACE_TYPE_SDL:
 
 <!-- ##### FUNCTION cairo_surface_get_type ##### -->
 <para>
diff --git a/test/.gitignore b/test/.gitignore
index 675315a..ad70768 100644
--- a/test/.gitignore
+++ b/test/.gitignore
@@ -2,249 +2,20 @@ TAGS
 tags
 .deps
 .libs
+output
 Makefile
 Makefile.in
 index.html
 ref.hash
-a1-image-sample
-a1-mask
-a1-traps-sample
-a8-mask
-alpha-similar
 any2ppm
 .any2ppm
 .any2ppm.pid
-big-line
-big-trap
-bilevel-image
-bitmap-font
-caps-joins
-caps-joins-alpha
-caps-sub-paths
-clip-all
-clip-empty
-clip-fill-rule
-clip-fill-rule-pixel-aligned
-clip-nesting
-clip-operator
-clip-push-group
-clip-twice
-clip-zero
-clipped-group
-clipped-surface
-close-path
-composite-integer-translate-over
-composite-integer-translate-over-repeat
-composite-integer-translate-source
-copy-path
-coverage
-create-for-stream
-create-for-stream.pdf
-create-for-stream.ps
-create-for-stream.svg
-create-from-png
-create-from-png-stream
-dash-caps-joins
-dash-curve
-dash-no-dash
-dash-offset-negative
-dash-scale
-dash-state
-dash-zero-length
-degenerate-arc
-degenerate-dash
-degenerate-path
-degenerate-pen
-device-offset
-device-offset-fractional
-device-offset-positive
-device-offset-scale
-extend-pad
-extend-pad-similar
-extend-reflect
-extend-reflect-similar
-extend-repeat
-extend-repeat-similar
-fallback-resolution
-fallback-resolution.pdf
-fallback-resolution.ps
-fallback-resolution.svg
-fill-alpha
-fill-alpha-pattern
-fill-and-stroke
-fill-and-stroke-alpha
-fill-and-stroke-alpha-add
-fill-degenerate-sort-order
-fill-missed-stop
-fill-rule
-filter-bilinear-extents
-filter-nearest-offset
-filter-nearest-transformed
-finer-grained-fallbacks
-ft-text-antialias-none
-ft-font-create-for-ft-face
-ft-show-glyphs-positioning
-ft-show-glyphs-table
-ft-text-vertical-layout-type1
-ft-text-vertical-layout-type3
-font-face-get-type
-font-matrix-translation
-font-options
-get-and-set
-get-clip
-get-group-target
-get-path-extents
-get-xrender-format
-glitz-surface-source
-glyph-cache-pressure
-gradient-alpha
-gradient-constant-alpha
-gradient-zero-stops
-group-paint
-huge-pattern
-imagediff
-image-surface-source
-infinite-join
-in-fill-empty-trapezoid
-in-fill-trapezoid
-invalid-matrix
-large-clip
-large-font
-large-source
-leaky-dash
-leaky-dashed-rectangle
-leaky-dashed-stroke
-leaky-polygon
-line-width
-line-width-scale
-line-width-zero
-linear-gradient
-linear-gradient-reflect
-long-dashed-lines
-long-lines
-mask
-mask-alpha
-mask-ctm
-mask-surface-ctm
-mask-transformed-image
-mask-transformed-similar
-meta-surface-pattern
-miter-precision
-move-to-show-surface
-multi-page
-multi-page.pdf
-multi-page.ps
-new-sub-path
-nil-surface
-operator
-operator-alpha
-operator-clear
-operator-source
-over-above-source
-over-around-source
-over-below-source
-over-between-source
-paint
-paint-repeat
-paint-source-alpha
-paint-with-alpha
-pass-through
-path-data
-pattern-get-type
-pattern-getters
+.any2ppm.errors
+cairo-test-constructors.c
+cairo-test-suite
 pdf2png
-pdf-features
-pdf-features.pdf
-pdf-surface-source
-pdf-surface-source.pdf
-png
-png-test.png
-png-flatten
 ps2png
-ps-features
-ps-features.ps
-ps-surface-source
-ps-surface-source.ps
-push-group
-radial-gradient
-random-intersections
-rgb24-ignore-alpha
 svg2png
-svg-clip
-svg-clip.svg
-svg-surface
-svg-surface.svg
-svg-surface-source
-svg-surface-source.svg
-pixman-rotate
-pthread-show-text
-rectangle-rounding-error
-rectilinear-fill
-rectilinear-miter-limit
-rectilinear-stroke
-reflected-stroke
-rel-path
-rotate-image-surface-paint
-scale-down-source-surface-paint
-scale-source-surface-paint
-select-font-face
-select-font-no-show-text
-self-copy
-self-copy-overlap
-self-intersecting
-set-source
-show-glyphs-many
-show-text-current-point
-skew-extreme
-smask
-smask-fill
-smask-image-mask
-smask-mask
-smask-paint
-smask-stroke
-smask-text
-solid-pattern-cache-stress
-source-clip
-source-clip-scale
-source-surface-scale-paint
-spline-decomposition
-stroke-image
-stroke-ctm-caps
-surface-finish-twice
-surface-pattern
-surface-pattern-big-scale-down
-surface-pattern-scale-down
-surface-pattern-scale-up
-text-antialias-gray
-text-antialias-none
-text-antialias-subpixel
-text-cache-crash
-text-glyph-range
-text-lcd-filter-fir3
-text-lcd-filter-fir5
-text-lcd-filter-intra-pixel
-text-lcd-filter-none
-text-pattern
-text-rotate
-text-transform
-text-zero-len
-toy-font-face
-transforms
-translate-show-surface
-trap-clip
-truetype-tables
-twin
-unantialiased-shapes
-unbounded-operator
-user-data
-user-font
-user-font-mask
-user-font-proxy
-user-font-rescale
-xlib-expose-event
-xlib-surface
-xlib-surface-source
-zero-alpha
 valgrind-log
 *-out.*
 *-pass.*
diff --git a/test/Makefile.am b/test/Makefile.am
index 11dff25..46c68ba 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -2,286 +2,293 @@ include $(top_srcdir)/build/Makefile.am.common
 
 SUBDIRS=pdiff .
 
-# Here are all the tests that are run unconditionally
-TESTS +=						\
-a1-image-sample$(EXEEXT)				\
-a1-mask$(EXEEXT)					\
-a1-traps-sample$(EXEEXT)				\
-a8-mask$(EXEEXT)					\
-alpha-similar$(EXEEXT)					\
-big-line$(EXEEXT)					\
-big-trap$(EXEEXT)					\
-bilevel-image$(EXEEXT)					\
-caps-joins$(EXEEXT)					\
-caps-joins-alpha$(EXEEXT)				\
-caps-sub-paths$(EXEEXT)					\
-clip-all$(EXEEXT)					\
-clip-empty$(EXEEXT)					\
-clip-fill-rule$(EXEEXT)					\
-clip-fill-rule-pixel-aligned$(EXEEXT)			\
-clip-nesting$(EXEEXT)					\
-clip-operator$(EXEEXT)					\
-clip-push-group$(EXEEXT)				\
-clip-twice$(EXEEXT)					\
-clip-zero$(EXEEXT)					\
-clipped-group$(EXEEXT)					\
-clipped-surface$(EXEEXT)				\
-close-path$(EXEEXT)					\
-composite-integer-translate-source$(EXEEXT)		\
-composite-integer-translate-over$(EXEEXT)		\
-composite-integer-translate-over-repeat$(EXEEXT)	\
-copy-path$(EXEEXT)					\
-create-for-stream$(EXEEXT)				\
-create-from-png$(EXEEXT)				\
-create-from-png-stream$(EXEEXT)				\
-dash-caps-joins$(EXEEXT)				\
-dash-curve$(EXEEXT)					\
-dash-no-dash$(EXEEXT)					\
-dash-offset-negative$(EXEEXT)				\
-dash-scale$(EXEEXT)					\
-dash-state$(EXEEXT)					\
-dash-zero-length$(EXEEXT)				\
-degenerate-arc$(EXEEXT)					\
-degenerate-dash$(EXEEXT)				\
-degenerate-path$(EXEEXT)				\
-degenerate-pen$(EXEEXT)					\
-device-offset$(EXEEXT)					\
-device-offset-fractional$(EXEEXT)			\
-device-offset-positive$(EXEEXT)				\
-device-offset-scale$(EXEEXT)				\
-extend-pad$(EXEEXT)					\
-extend-reflect$(EXEEXT)					\
-extend-reflect-similar$(EXEEXT)				\
-extend-repeat$(EXEEXT)					\
-extend-repeat-similar$(EXEEXT)				\
-fill-alpha$(EXEEXT)					\
-fill-alpha-pattern$(EXEEXT)				\
-fill-and-stroke$(EXEEXT)				\
-fill-and-stroke-alpha$(EXEEXT)				\
-fill-and-stroke-alpha-add$(EXEEXT)			\
-fill-degenerate-sort-order$(EXEEXT)			\
-fill-missed-stop$(EXEEXT)				\
-fill-rule$(EXEEXT)					\
-filter-bilinear-extents$(EXEEXT)			\
-filter-nearest-offset$(EXEEXT)				\
-filter-nearest-transformed$(EXEEXT)			\
-finer-grained-fallbacks$(EXEEXT)			\
-font-face-get-type$(EXEEXT)				\
-font-matrix-translation$(EXEEXT)			\
-font-options$(EXEEXT)					\
-glyph-cache-pressure$(EXEEXT)				\
-get-and-set$(EXEEXT)					\
-get-clip$(EXEEXT)					\
-get-group-target$(EXEEXT)				\
-get-path-extents$(EXEEXT)				\
-gradient-alpha$(EXEEXT)					\
-gradient-constant-alpha$(EXEEXT)			\
-gradient-zero-stops$(EXEEXT)				\
-group-paint$(EXEEXT)					\
-huge-pattern$(EXEEXT)					\
-image-surface-source$(EXEEXT)				\
-infinite-join$(EXEEXT)					\
-in-fill-empty-trapezoid$(EXEEXT)			\
-in-fill-trapezoid$(EXEEXT)				\
-invalid-matrix$(EXEEXT)					\
-large-clip$(EXEEXT)					\
-large-font$(EXEEXT)					\
-large-source$(EXEEXT)					\
-leaky-dash$(EXEEXT)					\
-leaky-dashed-rectangle$(EXEEXT)				\
-leaky-dashed-stroke$(EXEEXT)				\
-leaky-polygon$(EXEEXT)					\
-line-width$(EXEEXT)					\
-line-width-scale$(EXEEXT)				\
-line-width-zero$(EXEEXT)				\
-linear-gradient$(EXEEXT)				\
-linear-gradient-reflect$(EXEEXT)			\
-long-dashed-lines$(EXEEXT)				\
-long-lines$(EXEEXT)					\
-mask$(EXEEXT)						\
-mask-alpha$(EXEEXT)					\
-mask-ctm$(EXEEXT)					\
-mask-surface-ctm$(EXEEXT)				\
-mask-transformed-image$(EXEEXT)				\
-mask-transformed-similar$(EXEEXT)			\
-meta-surface-pattern$(EXEEXT)				\
-miter-precision$(EXEEXT)				\
-move-to-show-surface$(EXEEXT)				\
-new-sub-path$(EXEEXT)					\
-nil-surface$(EXEEXT)					\
-operator$(EXEEXT)					\
-operator-alpha$(EXEEXT)					\
-operator-clear$(EXEEXT)					\
-operator-source$(EXEEXT)				\
-over-above-source$(EXEEXT)				\
-over-around-source$(EXEEXT)				\
-over-below-source$(EXEEXT)				\
-over-between-source$(EXEEXT)				\
-paint$(EXEEXT)						\
-paint-repeat$(EXEEXT)					\
-paint-source-alpha$(EXEEXT)				\
-paint-with-alpha$(EXEEXT)				\
-pass-through$(EXEEXT)					\
-pattern-get-type$(EXEEXT)				\
-pattern-getters$(EXEEXT)				\
-pixman-rotate$(EXEEXT)					\
-png$(EXEEXT)						\
-push-group$(EXEEXT)					\
-radial-gradient$(EXEEXT)				\
-random-intersections$(EXEEXT)				\
-rectangle-rounding-error$(EXEEXT)			\
-rectilinear-fill$(EXEEXT)				\
-rectilinear-miter-limit$(EXEEXT)			\
-rectilinear-stroke$(EXEEXT)				\
-reflected-stroke$(EXEEXT)				\
-rel-path$(EXEEXT)					\
-rgb24-ignore-alpha$(EXEEXT)				\
-rotate-image-surface-paint$(EXEEXT)			\
-scale-down-source-surface-paint$(EXEEXT)		\
-scale-source-surface-paint$(EXEEXT)			\
-stroke-ctm-caps$(EXEEXT)				\
-stroke-image$(EXEEXT)				        \
-select-font-face$(EXEEXT)				\
-select-font-no-show-text$(EXEEXT)			\
-self-copy$(EXEEXT)					\
-self-copy-overlap$(EXEEXT)				\
-self-intersecting$(EXEEXT)				\
-set-source$(EXEEXT)					\
-show-glyphs-many$(EXEEXT)				\
-show-text-current-point$(EXEEXT)			\
-skew-extreme$(EXEEXT)					\
-smask$(EXEEXT)						\
-smask-fill$(EXEEXT)					\
-smask-image-mask$(EXEEXT)				\
-smask-mask$(EXEEXT)					\
-smask-paint$(EXEEXT)					\
-smask-stroke$(EXEEXT)					\
-smask-text$(EXEEXT)					\
-solid-pattern-cache-stress$(EXEEXT)			\
-source-clip$(EXEEXT)					\
-source-clip-scale$(EXEEXT)				\
-source-surface-scale-paint$(EXEEXT)			\
-spline-decomposition$(EXEEXT)				\
-surface-finish-twice$(EXEEXT)				\
-surface-pattern$(EXEEXT)				\
-surface-pattern-big-scale-down$(EXEEXT)			\
-surface-pattern-scale-down$(EXEEXT)			\
-surface-pattern-scale-up$(EXEEXT)			\
-text-antialias-gray$(EXEEXT)				\
-text-antialias-none$(EXEEXT)				\
-text-antialias-subpixel$(EXEEXT)			\
-text-cache-crash$(EXEEXT)				\
-text-pattern$(EXEEXT)					\
-text-rotate$(EXEEXT)					\
-text-transform$(EXEEXT)					\
-text-zero-len$(EXEEXT)					\
-toy-font-face$(EXEEXT)					\
-transforms$(EXEEXT)					\
-translate-show-surface$(EXEEXT)				\
-trap-clip$(EXEEXT)					\
-truetype-tables$(EXEEXT)				\
-twin$(EXEEXT)						\
-unantialiased-shapes$(EXEEXT)				\
-unbounded-operator$(EXEEXT)				\
-user-data$(EXEEXT)					\
-user-font$(EXEEXT)					\
-user-font-mask$(EXEEXT)					\
-user-font-proxy$(EXEEXT)				\
-user-font-rescale$(EXEEXT)				\
-zero-alpha$(EXEEXT)
+CLEANFILES += have-similar.*
 
-# XXX: Here are some existing tests that are currently disabled for
-# one reason or another. They can still be built and run (manually)
-# but we don't currently run them as part of 'make check' to avoid
-# inflicting some particularly nasty problems on the user of the test
-# suite (described below).
-#
-# It would definitely be worthwhile to address these problems so that
-# these tests can get back into the test suite proper, (since the
-# problems do indicated bugs somewhere and we're less likely to get
-# those bugs fixed without the attention due to having these tests in
-# the suite).
-#
-# The reasons for disabling the tests are as follows:
-#
-# extend-reflect - Triggers an infinite (or near-infinite) bug in some
-#	X servers in some circumstances. Details and cause unknown.
-#
-# text-glyph-range - This test triggers the following assertion in cairo:
-#
-#	lt-text-glyph-range: cairo-scaled-font-subsets.c:350:
-#	_cairo_sub_font_collect: Assertion `collection->num_glyphs ==
-#	collection->max_glyph + 1' failed.
-#
-#	And as a result causes a failure to be recorded by the test
-#	suite, (in spite of the XFAIL status of the test). So maybe
-#	that's just a bug in the test rig that should just consider
-#	the abort an XFAIL like any other.
-DISABLED_TESTS =			\
-text-glyph-range$(EXEEXT)
+test_sources = \
+	a1-image-sample.c 				\
+	a1-mask.c					\
+	a1-traps-sample.c				\
+	a8-mask.c					\
+	alpha-similar.c					\
+	big-line.c					\
+	big-trap.c					\
+	bilevel-image.c					\
+	caps-joins.c					\
+	caps-joins-alpha.c				\
+	caps-sub-paths.c				\
+	clip-all.c					\
+	clip-empty.c					\
+	clip-fill-rule.c				\
+	clip-fill-rule-pixel-aligned.c			\
+	clip-nesting.c					\
+	clip-operator.c					\
+	clip-push-group.c				\
+	clip-twice.c					\
+	clip-zero.c					\
+	clipped-group.c					\
+	clipped-surface.c				\
+	close-path.c					\
+	composite-integer-translate-source.c		\
+	composite-integer-translate-over.c		\
+	composite-integer-translate-over-repeat.c	\
+	copy-path.c					\
+	create-for-stream.c				\
+	create-from-png.c				\
+	create-from-png-stream.c			\
+	dash-caps-joins.c				\
+	dash-curve.c					\
+	dash-no-dash.c					\
+	dash-offset-negative.c				\
+	dash-scale.c					\
+	dash-state.c					\
+	dash-zero-length.c				\
+	degenerate-arc.c				\
+	degenerate-dash.c				\
+	degenerate-path.c				\
+	degenerate-pen.c				\
+	device-offset.c					\
+	device-offset-fractional.c			\
+	device-offset-positive.c			\
+	device-offset-scale.c				\
+	extend-pad.c					\
+	extend-reflect.c				\
+	extend-reflect-similar.c			\
+	extend-repeat.c					\
+	extend-repeat-similar.c				\
+	fill-alpha.c					\
+	fill-alpha-pattern.c				\
+	fill-and-stroke.c				\
+	fill-and-stroke-alpha.c				\
+	fill-and-stroke-alpha-add.c			\
+	fill-degenerate-sort-order.c			\
+	fill-missed-stop.c				\
+	fill-rule.c					\
+	filter-bilinear-extents.c			\
+	filter-nearest-offset.c				\
+	filter-nearest-transformed.c			\
+	finer-grained-fallbacks.c			\
+	font-face-get-type.c				\
+	font-matrix-translation.c			\
+	font-options.c					\
+	glyph-cache-pressure.c				\
+	get-and-set.c					\
+	get-clip.c					\
+	get-group-target.c				\
+	get-path-extents.c				\
+	gradient-alpha.c				\
+	gradient-constant-alpha.c			\
+	gradient-zero-stops.c				\
+	group-paint.c					\
+	huge-pattern.c					\
+	image-surface-source.c				\
+	infinite-join.c					\
+	in-fill-empty-trapezoid.c			\
+	in-fill-trapezoid.c				\
+	invalid-matrix.c				\
+	large-clip.c					\
+	large-font.c					\
+	large-source.c					\
+	leaky-dash.c					\
+	leaky-dashed-rectangle.c			\
+	leaky-dashed-stroke.c				\
+	leaky-polygon.c					\
+	line-width.c					\
+	line-width-scale.c				\
+	line-width-zero.c				\
+	linear-gradient.c				\
+	linear-gradient-reflect.c			\
+	long-dashed-lines.c				\
+	long-lines.c					\
+	mask.c						\
+	mask-alpha.c					\
+	mask-ctm.c					\
+	mask-surface-ctm.c				\
+	mask-transformed-image.c			\
+	mask-transformed-similar.c			\
+	meta-surface-pattern.c				\
+	miter-precision.c				\
+	move-to-show-surface.c				\
+	new-sub-path.c					\
+	nil-surface.c					\
+	operator.c					\
+	operator-alpha.c				\
+	operator-clear.c				\
+	operator-source.c				\
+	over-above-source.c				\
+	over-around-source.c				\
+	over-below-source.c				\
+	over-between-source.c				\
+	paint.c						\
+	paint-repeat.c					\
+	paint-source-alpha.c				\
+	paint-with-alpha.c				\
+	pattern-get-type.c				\
+	pattern-getters.c				\
+	pixman-rotate.c					\
+	png.c						\
+	push-group.c					\
+	radial-gradient.c				\
+	random-intersections.c				\
+	rectangle-rounding-error.c			\
+	rectilinear-fill.c				\
+	rectilinear-miter-limit.c			\
+	rectilinear-stroke.c				\
+	reflected-stroke.c				\
+	rel-path.c					\
+	rgb24-ignore-alpha.c				\
+	rotate-image-surface-paint.c			\
+	scale-down-source-surface-paint.c		\
+	scale-source-surface-paint.c			\
+	stroke-ctm-caps.c				\
+	stroke-image.c				        \
+	select-font-face.c				\
+	select-font-no-show-text.c			\
+	self-copy.c					\
+	self-copy-overlap.c				\
+	self-intersecting.c				\
+	set-source.c					\
+	show-glyphs-many.c				\
+	show-text-current-point.c			\
+	skew-extreme.c					\
+	smask.c						\
+	smask-fill.c					\
+	smask-image-mask.c				\
+	smask-mask.c					\
+	smask-paint.c					\
+	smask-stroke.c					\
+	smask-text.c					\
+	solid-pattern-cache-stress.c			\
+	source-clip.c					\
+	source-clip-scale.c				\
+	source-surface-scale-paint.c			\
+	spline-decomposition.c				\
+	surface-finish-twice.c				\
+	surface-pattern.c				\
+	surface-pattern-big-scale-down.c		\
+	surface-pattern-scale-down.c			\
+	surface-pattern-scale-up.c			\
+	text-antialias-gray.c				\
+	text-antialias-none.c				\
+	text-antialias-subpixel.c			\
+	text-cache-crash.c				\
+	text-glyph-range.c				\
+	text-pattern.c					\
+	text-rotate.c					\
+	text-transform.c				\
+	text-zero-len.c					\
+	toy-font-face.c					\
+	transforms.c					\
+	translate-show-surface.c			\
+	trap-clip.c					\
+	truetype-tables.c				\
+	twin.c						\
+	unantialiased-shapes.c				\
+	unbounded-operator.c				\
+	user-data.c					\
+	user-font.c					\
+	user-font-mask.c				\
+	user-font-proxy.c				\
+	user-font-rescale.c				\
+	zero-alpha.c
 
 # Then we have a collection of tests that are only run if certain
 # features are compiled into cairo
 if HAVE_PTHREAD
-TESTS += pthread-show-text$(EXEEXT)
+test_sources += pthread-show-text.c
 endif
 
 if CAIRO_HAS_FT_FONT
-TESTS += bitmap-font$(EXEEXT)
-TESTS += ft-font-create-for-ft-face$(EXEEXT)
-TESTS += ft-show-glyphs-positioning$(EXEEXT)
-TESTS += ft-show-glyphs-table$(EXEEXT)
-TESTS += ft-text-vertical-layout-type1$(EXEEXT)
-TESTS += ft-text-vertical-layout-type3$(EXEEXT)
-TESTS += ft-text-antialias-none$(EXEEXT)
+test_sources += bitmap-font.c
+test_sources += ft-font-create-for-ft-face.c
+test_sources += ft-show-glyphs-positioning.c
+test_sources += ft-show-glyphs-table.c
+test_sources += ft-text-vertical-layout-type1.c
+test_sources += ft-text-vertical-layout-type3.c
+test_sources += ft-text-antialias-none.c
 endif
 
 # Need to add win32-surface-source, quartz-surface-source
 if CAIRO_HAS_GLITZ_SURFACE
-TESTS += glitz-surface-source$(EXEEXT)
+test_sources += glitz-surface-source.c
 endif
 
 if CAIRO_HAS_PDF_SURFACE
-TESTS += pdf-features$(EXEEXT)
-TESTS += pdf-surface-source$(EXEEXT)
+test_sources += pdf-features.c
+test_sources += pdf-surface-source.c
 endif
 
 if CAIRO_HAS_PS_SURFACE
-TESTS += ps-features$(EXEEXT)
-TESTS += ps-surface-source$(EXEEXT)
+test_sources += ps-features.c
+test_sources += ps-surface-source.c
 endif
 
 if CAIRO_HAS_SVG_SURFACE
-TESTS += svg-surface$(EXEEXT)
-TESTS += svg-clip$(EXEEXT)
-TESTS += svg-surface-source$(EXEEXT)
+test_sources += svg-surface.c
+test_sources += svg-clip.c
+test_sources += svg-surface-source.c
 endif
 
 if CAIRO_HAS_XLIB_SURFACE
-TESTS += xlib-expose-event$(EXEEXT)
-TESTS += xlib-surface$(EXEEXT)
-TESTS += xlib-surface-source$(EXEEXT)
+test_sources += xlib-expose-event.c
+test_sources += xlib-surface.c
+test_sources += xlib-surface-source.c
 endif
 
 if CAIRO_HAS_XLIB_XRENDER_SURFACE
-TESTS += get-xrender-format$(EXEEXT)
+test_sources += get-xrender-format.c
 endif
 
 if CAIRO_HAS_MULTI_PAGE_SURFACES
-TESTS += multi-page$(EXEEXT)
+test_sources += multi-page.c
 endif
 
 # Include fallback-resolution (once!) if we have any of the vector surfaces
 if CAIRO_HAS_SVG_SURFACE
-test = fallback-resolution$(EXEEXT)
+test = fallback-resolution.c
 endif
 if CAIRO_HAS_PDF_SURFACE
-test = fallback-resolution$(EXEEXT)
+test = fallback-resolution.c
 endif
 if CAIRO_HAS_PS_SURFACE
-test = fallback-resolution$(EXEEXT)
+test = fallback-resolution.c
+endif
+test_sources += $(test)
+
+TESTS += cairo-test-suite$(EXEEXT)
+
+cairo-test-constructors.c: Makefile $(test_sources) make-cairo-test-constructors.pl
+	@(cd $(srcdir) && ./make-cairo-test-constructors.pl $(test_sources)) > $@
+
+cairo_test_suite_SOURCES = 		\
+	buffer-diff.c			\
+	buffer-diff.h			\
+	cairo-test.c			\
+	cairo-test.h			\
+	cairo-test-private.h		\
+	cairo-test-runner.c		\
+	$(test_sources)
+if CAIRO_HAS_CONSTRUCTOR_ATTRIBUTE
+else
+cairo_test_suite_SOURCES += cairo-test-constructors.c
+endif
+cairo_test_suite_LDADD = 					\
+	$(top_builddir)/test/pdiff/libpdiff.la 			\
+        $(top_builddir)/boilerplate/libcairoboilerplate.la	\
+	$(top_builddir)/src/libcairo.la 			\
+	$(CAIRO_LDADD)
+cairo_test_suite_DEPENDENCIES = \
+	$(top_builddir)/test/pdiff/libpdiff.la 			\
+        $(top_builddir)/boilerplate/libcairoboilerplate.la	\
+	$(top_builddir)/src/libcairo.la 			\
+	any2ppm
+if HAVE_PTHREAD
+cairo_test_suite_LDADD += -lpthread
 endif
-TESTS += $(test)
+
+BUILT_SOURCES += cairo-test-constructors.c
+noinst_SCRIPTS = make-cairo-test-constructors.pl
+EXTRA_DIST += $(BUILT_SOURCES) $(noinst_SCRIPTS)
+CLEANFILES += $(BUILT_SOURCES)
 
 # All tests which have a reference image go here.
 REFERENCE_IMAGES = \
@@ -885,7 +892,7 @@ REFERENCE_IMAGES = \
 	surface-pattern-ps2-ref.png	\
 	surface-pattern-ps3-ref.png	\
 	surface-pattern-ref.png	\
-	surface-pattern-scale-down-pdf-argb24-ref.png	\
+	surface-pattern-scale-down-pdf-argb32-ref.png	\
 	surface-pattern-scale-down-pdf-rgb24-ref.png	\
 	surface-pattern-scale-down-ps2-ref.png	\
 	surface-pattern-scale-down-ps3-ref.png	\
@@ -906,7 +913,8 @@ REFERENCE_IMAGES = \
 	text-antialias-subpixel-ref.png	\
 	text-antialias-subpixel-quartz-ref.png	\
 	text-glyph-range-ref.png	\
-	text-glyph-range-rgb24-ref.png	\
+	text-glyph-range-ps2-ref.png	\
+	text-glyph-range-ps3-ref.png	\
 	text-pattern-ps3-argb32-ref.png	\
 	text-pattern-ps3-rgb24-ref.png	\
 	text-pattern-ref.png	\
@@ -1068,13 +1076,10 @@ svg-surface			\
 toy-font-face			\
 user-data
 
-# A hook that summarises the failures
-# We need to both force make to keep going after failures and to disable the
-# jobserver (parallel builds).
-check: AM_MAKEFLAGS+=-k -j1
-check-local:
+# A target to summarise the failures
+check-summary:
 	@FAILED_TESTS=""; \
-	for t in $(TESTS:$(EXEEXT)=.log); do \
+	for t in $(test_sources:.c=.log); do \
 	    if grep -e '\<FAIL\>' $$t >/dev/null 2>&1; then \
 		FAILED_TESTS="$$FAILED_TESTS $${t%.log}"; \
 	    fi; \
@@ -1119,21 +1124,6 @@ AM_CPPFLAGS =					\
 	-I$(top_builddir)/src			\
 	$(CAIRO_CFLAGS)
 
-EXTRA_LTLIBRARIES += libcairotest.la
-
-libcairotest_la_SOURCES =\
-	buffer-diff.c	\
-	buffer-diff.h	\
-	cairo-test.c	\
-	cairo-test.h
-libcairotest_la_LIBADD =\
-	$(top_builddir)/test/pdiff/libpdiff.la \
-        $(top_builddir)/boilerplate/libcairoboilerplate.la \
-	$(top_builddir)/src/libcairo.la \
-	$(CAIRO_LDADD)
-
-LDADD = $(CAIRO_LDADD) libcairotest.la
-
 $(top_builddir)/boilerplate/libcairoboilerplate.la: $(top_builddir)/src/libcairo.la
 	cd $(top_builddir)/boilerplate && $(MAKE) $(AM_MAKEFLAGS) libcairoboilerplate.la
 
@@ -1143,18 +1133,24 @@ $(top_builddir)/src/libcairo.la:
 $(top_builddir)/test/pdiff/libpdiff.la:
 	cd $(top_builddir)/test/pdiff && $(MAKE) $(AM_MAKEFLAGS) libpdiff.la
 
-if HAVE_PTHREAD
-LDADD += -lpthread
-endif
+EXTRA_PROGRAMS += imagediff png-flatten
+
+imagediff_SOURCES = \
+	imagediff.c	\
+	buffer-diff.c	\
+	buffer-diff.h
+imagediff_LDADD = \
+	$(top_builddir)/test/pdiff/libpdiff.la
 
-check_PROGRAMS += imagediff png-flatten
+png_flatten_SOURCES = png-flatten.c
+png_flatten_LDADD = $(top_builddir)/src/libcairo.la $(CAIRO_LDADD)
 
 if BUILD_ANY2PPM
 check_PROGRAMS += any2ppm
 any2ppm_CFLAGS = $(POPPLER_CFLAGS) $(LIBRSVG_CFLAGS) $(LIBSPECTRE_CFLAGS)
 # add LDADD, so poppler/librsvg uses "our" cairo
 any2ppm_LDFLAGS = $(CAIRO_TEST_UNDEFINED_LDFLAGS)
-any2ppm_LDADD  = $(LDADD) $(POPPLER_LIBS) $(LIBRSVG_LIBS) $(LIBSPECTRE_LIBS)
+any2ppm_LDADD  = $(top_builddir)/src/libcairo.la $(CAIRO_LDADD) $(POPPLER_LIBS) $(LIBRSVG_LIBS) $(LIBSPECTRE_LIBS)
 endif
 
 if CAIRO_CAN_TEST_PDF_SURFACE
@@ -1162,7 +1158,7 @@ check_PROGRAMS += pdf2png
 pdf2png_CFLAGS = $(POPPLER_CFLAGS)
 # add LDADD, so poppler uses "our" cairo
 pdf2png_LDFLAGS = $(CAIRO_TEST_UNDEFINED_LDFLAGS)
-pdf2png_LDADD  = $(LDADD) $(POPPLER_LIBS)
+pdf2png_LDADD  = $(top_builddir)/src/libcairo.la $(CAIRO_LDADD) $(POPPLER_LIBS)
 endif
 
 if CAIRO_CAN_TEST_SVG_SURFACE
@@ -1170,7 +1166,7 @@ check_PROGRAMS += svg2png
 svg2png_CFLAGS = $(LIBRSVG_CFLAGS)
 # add LDADD, so librsvg uses "our" cairo
 svg2png_LDFLAGS = $(CAIRO_TEST_UNDEFINED_LDFLAGS)
-svg2png_LDADD  = $(LDADD) $(LIBRSVG_LIBS)
+svg2png_LDADD  = $(top_builddir)/src/libcairo.la $(CAIRO_LDADD) $(LIBRSVG_LIBS)
 endif
 
 if CAIRO_HAS_SPECTRE
@@ -1178,10 +1174,10 @@ check_PROGRAMS += ps2png
 ps2png_CFLAGS = $(LIBSPECTRE_CFLAGS)
 # add LDADD, so ps2png uses "our" cairo
 ps2png_LDFLAGS = $(CAIRO_TEST_UNDEFINED_LDFLAGS)
-ps2png_LDADD  = $(LDADD) $(LIBSPECTRE_LIBS)
+ps2png_LDADD  = $(top_builddir)/src/libcairo.la $(CAIRO_LDADD) $(LIBSPECTRE_LIBS)
 endif
 
-EXTRA_PROGRAMS += $(TESTS) $(DISABLED_TESTS)
+EXTRA_PROGRAMS += $(TESTS)
 
 # Do a funny transition of CAIRO_TEST_TARGET through TARGETS such that
 # one can limit tested targets both through CAIRO_TEST_TARGET env var
@@ -1189,11 +1185,12 @@ EXTRA_PROGRAMS += $(TESTS) $(DISABLED_TESTS)
 TARGETS = $(CAIRO_TEST_TARGET)
 TARGETS_EXCLUDE = $(CAIRO_TEST_TARGET_EXCLUDE)
 NUM_THREADS = $(CAIRO_TEST_NUM_THREADS)
+MODE = $(CAIRO_TEST_MODE)
 
 # Same about ENV vs CAIRO_TEST_ENV.  ENV is used with "make run" only
 ENV = $(CAIRO_TEST_ENV)
 
-TESTS_ENVIRONMENT = CAIRO_XFAIL_TESTS="$(XFAIL_TESTS:$(EXEEXT)=)" CAIRO_TEST_TARGET="$(TARGETS)" CAIRO_TEST_TARGET_EXCLUDE="$(TARGETS_EXCLUDE)" CAIRO_TEST_NUM_THREADS="$(NUM_THREADS)" $(ENV)
+TESTS_ENVIRONMENT = CAIRO_TEST_MODE="$(MODE)" CAIRO_TEST_TARGET="$(TARGETS)" CAIRO_TEST_TARGET_EXCLUDE="$(TARGETS_EXCLUDE)" CAIRO_TEST_NUM_THREADS="$(NUM_THREADS)" $(ENV)
 
 EXTRA_VALGRIND_FLAGS = $(CAIRO_EXTRA_VALGRIND_FLAGS)
 VALGRIND_FLAGS = \
@@ -1224,8 +1221,8 @@ CLEANFILES +=					\
 # Then it became a fancy find using many GNU extensions, but then the ugly
 # reality of portability was raised and it became....
 clean-local: clean-caches
+	rm -rf output
 	-${FIND} . -name '*-out.*'    -print | ${XARGS} ${RM}
-	-${FIND} . -name '*-diff.png' -print | ${XARGS} ${RM}
 	-${FIND} . -name '*.log'      -print | ${XARGS} ${RM}
 	-${FIND} . -name '*.[is]'     -print | ${XARGS} ${RM}
 clean-caches:
@@ -1233,10 +1230,10 @@ clean-caches:
 	-${FIND} . -name '*-fail.*'   -print | ${XARGS} ${RM}
 
 # The following definitions both should work.
-#FAILED_TESTS = `grep -l '\<FAIL\>' $(TESTS:$(EXEEXT)=.log) 2>/dev/null | sed -e 's/[.]log$$//' | xargs echo`
-FAILED_TESTS = `grep -l '\<FAIL\>' $(TESTS:$(EXEEXT)=.log) 2>/dev/null | tr '\n' ' ' | sed -e 's/[.]log  */ /g; s/^ //; s/ $$//'`
+#FAILED_TESTS = `grep -l '\<FAIL\>' $(test_sources:.c=.log) 2>/dev/null | sed -e 's/[.]log$$//' | xargs echo`
+FAILED_TESTS = `grep -l '\<FAIL\>' $(test_sources:.c=.log) 2>/dev/null | tr '\n' ' ' | sed -e 's/[.]log  */ /g; s/^ //; s/ $$//'`
 
-recheck = check TESTS="$(FAILED_TESTS)"
+recheck = check CAIRO_TESTS="$(FAILED_TESTS)"
 
 # Re-checks all failed tests, i.e. tests with a log file that has a failure
 recheck:
@@ -1252,18 +1249,18 @@ test:
 # Re-checks tests and creates index.html.
 # Target doesn't fail if tests fail.
 retest:
-	@TESTS="$(FAILED_TESTS)"; \
-	$(MAKE) $(AM_MAKEFLAGS) TESTS="$$TESTS" check; \
-	$(MAKE) $(AM_MAKEFLAGS) TESTS="$$TESTS" html
+	@CAIRO_TESTS="$(FAILED_TESTS)"; \
+	$(MAKE) $(AM_MAKEFLAGS) check; \
+	$(MAKE) $(AM_MAKEFLAGS) html
 
 # Make index.html with no dependency tracking.
 html-local:
 	@echo Creating index.html
-	@perl $(srcdir)/make-html.pl $(TESTS:$(EXEEXT)=.log) > index.html
+	@perl $(srcdir)/make-html.pl $(test_sources:.c=.log) > index.html
 
 # Make index.html with no dependency tracking, containing only the failed tests.
 rehtml:
-	@$(MAKE) $(AM_MAKEFLAGS) TESTS="$(FAILED_TESTS)" html
+	@CAIRO_TESTS="$(FAILED_TESTS)" $(MAKE) $(AM_MAKEFLAGS) html
 
 # Run tests under a tool specified by TOOL.  For example, make run TOOL=gdb
 run:
@@ -1273,18 +1270,15 @@ run:
 check-valgrind:
 	$(MAKE) $(AM_MAKEFLAGS) check TESTS_ENVIRONMENT='$(TESTS_ENVIRONMENT) $(top_builddir)/libtool --mode=execute valgrind $(VALGRIND_FLAGS)' 2>&1 | tee valgrind-log
 
-
-$(TESTS): $(check_PROGRAMS)
-
-%.log: % $(check_PROGRAMS)
-	-./$<
+%.log: %.c cairo-test-suite
+	-./cairo-test-suite $(<:.c=)
 
 NOLOG_TESTS_LOG = $(NOLOG_TESTS:=.log)
 
 $(NOLOG_TESTS_LOG):
 	@echo dummy > $@
 
-index.html: $(srcdir)/make-html.pl $(TESTS:$(EXEEXT)=.log)
+index.html: $(srcdir)/make-html.pl $(test_sources:.c=.log)
 	@echo Creating index.html
 	@perl $^ > $@
 
diff --git a/test/README b/test/README
index 57abef2..cb8a80e 100644
--- a/test/README
+++ b/test/README
@@ -18,7 +18,16 @@ visually see any failed renderings alongside the corresponding
 reference image, (and a diff image as well).
 
 The test suite needs to be run before any code is committed and before
-any release. See below for hints and rules governing the use of the suite:
+any release. See below for hints and rules governing the use of the suite.
+
+The test suite is built as a single binary, which allows you to choose
+individual or categories of tests to run. For example, if you want to
+run all text related tests you can use:
+    ./cairo-test-suite text
+Or if you want to check the current status of known failures:
+    ./cairo-test-suite XFAIL
+This binary should be backwards-compatible with all library versions,
+allowing you to compare current versus past behaviour for any test.
 
 Tailoring tests running
 -----------------------
@@ -29,10 +38,10 @@ to circumvent the "pass" requirements listed below.
 To limit the backends that the tests are run against, use the
 TARGETS make variable, that can also be passed to make.
 It should contain a (space-, comma-, etc-separated) list of backends to test.
-To limit the tests run, use the TESTS make variable, which should be a
-space-separated list of tests to run.  For example:
+To limit the tests run, use the CAIRO_TESTS environment variable, which
+should be a space-separated list of tests to run.  For example:
 
-  make test TARGETS=image,ps3 TESTS="zero-alpha"
+  CAIRO_TEST="zero-alpha" make test TARGETS=image,ps
 
 Another very handy mechanism when trying to fix bugs is:
 
@@ -53,19 +62,19 @@ Running tests under modified enviroments or tools
 To run tests under a tool like gdb, one can use the run target and
 the TOOL variable.  For example:
 
-  make run TOOL=gdb TARGETS=pdf TESTS=user-font
+  CAIRO_TESTS=user-font make run TOOL=gdb TARGETS=pdf
 
 If you want to run under valgrind, there is a specific target for that
 that also sets a bunch of useful valgrind options.  Try:
 
-  make check-valgrind TESTS=user-font
+  CAIRO_TESTS=user-font make check-valgrind
 
 You can run tests under a modified environment you can use the ENV
 make variable.  However, that environment will also affect the libtool
 wrapper of the tests.  To only affect the actual test binaries, pass
 such environment as TOOL:
 
-  make run TOOL="LD_PRELOAD=/path/to/something.so" TEST=user-font
+  CAIRO_TESTS=user-font make run TOOL="LD_PRELOAD=/path/to/something.so"
 
 Getting the elusive zero failures
 ---------------------------------
@@ -211,7 +220,7 @@ variable in Makefile.am.
 Before releasing
 ----------------
 All tests should return a result of PASS for all supported (those enabled by
-default) backends,  meaning all known bugs are fixed, resulting in the happy
+default) backends, meaning all known bugs are fixed, resulting in the happy
 message:
 
 	All XX tests passed
@@ -260,10 +269,9 @@ fill-alpha-pattern
 gradient-alpha
 gradient-constant-alpha
 linear-gradient
-trap-clip
-linear-gradient
 linear-gradient-reflect
 radial-gradient
+trap-clip
 
 Poppler renders patterned text as black
 https://bugs.freedesktop.org/show_bug.cgi?id=14577
diff --git a/test/a1-image-sample.c b/test/a1-image-sample.c
index 809078c..552e894 100644
--- a/test/a1-image-sample.c
+++ b/test/a1-image-sample.c
@@ -26,21 +26,12 @@
 
 #include "cairo-test.h"
 
-static cairo_test_draw_function_t draw;
-
 #define POINTS	10
 #define STEP	(1.0 / POINTS)
 #define PAD	1
 #define WIDTH	(PAD + POINTS * 2 + PAD)
 #define HEIGHT	(WIDTH)
 
-static const cairo_test_t test = {
-    "a1-image-sample",
-    "Test sample position when drawing images with FILTER_NEAREST",
-    WIDTH, HEIGHT,
-    draw
-};
-
 /* A single, black pixel */
 static const uint32_t black_pixel = 0xff000000;
 
@@ -78,8 +69,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (a1_image_sample,
+	    "Test sample position when drawing images with FILTER_NEAREST",
+	    "image, alpha", /* keywords */
+	    "target=raster", /* requirements */
+	    WIDTH, HEIGHT,
+	    NULL, draw)
diff --git a/test/a1-mask.c b/test/a1-mask.c
index e4638fe..0be1d07 100644
--- a/test/a1-mask.c
+++ b/test/a1-mask.c
@@ -27,8 +27,6 @@
 
 #include "cairo-test.h"
 
-static cairo_test_draw_function_t draw;
-
 #define MASK_WIDTH 10
 #define MASK_HEIGHT 8
 
@@ -48,14 +46,6 @@ static unsigned char mask[(MASK_WIDTH + 7) / 8 * MASK_HEIGHT] = {
     MASK,
 };
 
-static const cairo_test_t test = {
-    "a1-mask",
-    "test masks of CAIRO_FORMAT_A1",
-    MASK_WIDTH, MASK_HEIGHT,
-    draw
-};
-
-
 static cairo_test_status_t
 check_status (const cairo_test_context_t *ctx,
 	      cairo_status_t status,
@@ -148,20 +138,17 @@ draw (cairo_t *cr, int dst_width, int dst_height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
+static cairo_test_status_t
+preamble (cairo_test_context_t *ctx)
 {
-    cairo_test_context_t ctx;
+    cairo_test_status_t status = CAIRO_TEST_SUCCESS;
     int test_width;
 
-    cairo_test_init (&ctx, "a1-mask");
-
     /* first check the API strictness */
     for (test_width = 0; test_width < 40; test_width++) {
 	int test_stride = (test_width + 7) / 8;
 	int stride = cairo_format_stride_for_width (CAIRO_FORMAT_A1,
 						    test_width);
-	cairo_test_status_t status;
 	cairo_status_t expected;
 
 	/* First create a surface using the width as the stride,
@@ -170,14 +157,14 @@ main (void)
 	expected = (stride == test_stride) ?
 	    CAIRO_STATUS_SUCCESS : CAIRO_STATUS_INVALID_STRIDE;
 
-	status = test_surface_with_width_and_stride (&ctx,
+	status = test_surface_with_width_and_stride (ctx,
 						     test_width,
 						     test_stride,
 						     expected);
 	if (status)
 	    return status;
 
-	status = test_surface_with_width_and_stride (&ctx,
+	status = test_surface_with_width_and_stride (ctx,
 						     test_width,
 						     -test_stride,
 						     expected);
@@ -188,14 +175,14 @@ main (void)
 	/* Then create a surface using the correct stride,
 	 * (should always succeed).
 	 */
-	status = test_surface_with_width_and_stride (&ctx,
+	status = test_surface_with_width_and_stride (ctx,
 						     test_width,
 						     stride,
 						     CAIRO_STATUS_SUCCESS);
 	if (status)
 	    return status;
 
-	status = test_surface_with_width_and_stride (&ctx,
+	status = test_surface_with_width_and_stride (ctx,
 						     test_width,
 						     -stride,
 						     CAIRO_STATUS_SUCCESS);
@@ -203,7 +190,12 @@ main (void)
 	    return status;
     }
 
-    cairo_test_fini (&ctx);
-
-    return cairo_test (&test);
+    return status;
 }
+
+CAIRO_TEST (a1_mask,
+            "test masks of CAIRO_FORMAT_A1",
+	    "alpha, mask", /* keywords */
+	    NULL, /* requirements */
+	    MASK_WIDTH, MASK_HEIGHT,
+	    preamble, draw)
diff --git a/test/a1-traps-sample.c b/test/a1-traps-sample.c
index 956d6a7..5bb97bb 100644
--- a/test/a1-traps-sample.c
+++ b/test/a1-traps-sample.c
@@ -26,21 +26,12 @@
 
 #include "cairo-test.h"
 
-static cairo_test_draw_function_t draw;
-
 #define POINTS	10
 #define STEP	(1.0 / POINTS)
 #define PAD	1
 #define WIDTH	(PAD + POINTS * 2 + PAD)
 #define HEIGHT	(WIDTH)
 
-static const cairo_test_t test = {
-    "a1-traps-sample",
-    "Test sample position when drawing trapezoids with ANTIALIAS_NONE",
-    WIDTH, HEIGHT,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -65,8 +56,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (a1_traps_sample,
+	    "Test sample position when drawing trapezoids with ANTIALIAS_NONE",
+	    "alpha, traps", /* keywords */
+	    "target=raster", /* requirements */
+	    WIDTH, HEIGHT,
+	    NULL, draw)
diff --git a/test/a8-mask.c b/test/a8-mask.c
index 47f9f5b..ec70812 100644
--- a/test/a8-mask.c
+++ b/test/a8-mask.c
@@ -26,15 +26,6 @@
 
 #include "cairo-test.h"
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "a8-mask",
-    "test masks of CAIRO_FORMAT_A8",
-    8, 8,
-    draw
-};
-
 #define MASK_WIDTH 8
 #define MASK_HEIGHT 8
 
@@ -149,18 +140,15 @@ draw (cairo_t *cr, int dst_width, int dst_height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
+static cairo_test_status_t
+preamble (cairo_test_context_t *ctx)
 {
-    cairo_test_context_t ctx;
+    cairo_test_status_t status = CAIRO_TEST_SUCCESS;
     int test_width;
 
-    cairo_test_init (&ctx, "a8-mask");
-
     for (test_width = 0; test_width < 40; test_width++) {
 	int stride = cairo_format_stride_for_width (CAIRO_FORMAT_A8,
 						test_width);
-	cairo_test_status_t status;
 	cairo_status_t expected;
 
 	/* First create a surface using the width as the stride,
@@ -169,14 +157,14 @@ main (void)
 	expected = (stride == test_width) ?
 	    CAIRO_STATUS_SUCCESS : CAIRO_STATUS_INVALID_STRIDE;
 
-	status = test_surface_with_width_and_stride (&ctx,
+	status = test_surface_with_width_and_stride (ctx,
 						     test_width,
 						     test_width,
 						     expected);
 	if (status)
 	    return status;
 
-	status = test_surface_with_width_and_stride (&ctx,
+	status = test_surface_with_width_and_stride (ctx,
 						     test_width,
 						     -test_width,
 						     expected);
@@ -187,14 +175,14 @@ main (void)
 	/* Then create a surface using the correct stride,
 	 * (should always succeed).
 	 */
-	status = test_surface_with_width_and_stride (&ctx,
+	status = test_surface_with_width_and_stride (ctx,
 						     test_width,
 						     stride,
 						     CAIRO_STATUS_SUCCESS);
 	if (status)
 	    return status;
 
-	status = test_surface_with_width_and_stride (&ctx,
+	status = test_surface_with_width_and_stride (ctx,
 						     test_width,
 						     -stride,
 						     CAIRO_STATUS_SUCCESS);
@@ -202,7 +190,12 @@ main (void)
 	    return status;
     }
 
-    cairo_test_fini (&ctx);
-
-    return cairo_test (&test);
+    return status;
 }
+
+CAIRO_TEST (a8_mask,
+	    "test masks of CAIRO_FORMAT_A8",
+	    "alpha, mask", /* keywords */
+	    NULL, /* requirements */
+	    8, 8,
+	    preamble, draw)
diff --git a/test/alpha-similar.c b/test/alpha-similar.c
index 526f4d0..29c3aeb 100644
--- a/test/alpha-similar.c
+++ b/test/alpha-similar.c
@@ -25,16 +25,6 @@
 
 #include "cairo-test.h"
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "alpha-similar",
-    "Tests creation of similar alpha surfaces"
-    "\nApplication of a pure-alpha similar source is inconsistent across backends.",
-    10, 10,
-    draw
-};
-
 static cairo_surface_t *
 create_source (cairo_surface_t *target, int width, int height)
 {
@@ -70,8 +60,11 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (alpha_similar,
+	    "Tests creation of similar alpha surfaces"
+	    "\nApplication of a pure-alpha similar source is inconsistent across backends.",
+	    "XFAIL=ps,pdf,svg alpha, similar", /* keywords */
+	    NULL, /* requirements */
+	    10, 10,
+	    NULL, draw)
+
diff --git a/test/big-line.c b/test/big-line.c
index 253be3a..3ee6f43 100644
--- a/test/big-line.c
+++ b/test/big-line.c
@@ -25,16 +25,6 @@
 
 #include "cairo-test.h"
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "big-line",
-    "Test drawing of simple lines with positive and negative coordinates > 2^16\n"
-    "This currently fails because of 16-bit limitations in pixman.",
-    100, 100,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -63,8 +53,10 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (big_line,
+	    "Test drawing of simple lines with positive and negative coordinates > 2^16\n"
+	    "This currently fails because of 16-bit limitations in pixman.",
+	    "XFAIL line", /* keywords */
+	    NULL, /* requirements */
+	    100, 100,
+	    NULL, draw)
diff --git a/test/big-trap.c b/test/big-trap.c
index 400705e..38f2adb 100644
--- a/test/big-trap.c
+++ b/test/big-trap.c
@@ -25,8 +25,6 @@
 
 #include "cairo-test.h"
 
-static cairo_test_draw_function_t draw;
-
 /* This test was originally written to exercise a bug in pixman in
  * which it would scribble all over memory when given a particular
  * (and bogus) trapezoid. However, a recent change to
@@ -60,14 +58,6 @@ static cairo_test_draw_function_t draw;
  * will prevent the hiding of internal library symbols.
  */
 
-static const cairo_test_t test = {
-    "big-trap",
-    "Test oversize trapezoid with a clip region"
-    "\nTest needs to be adjusted to trigger the original bug",
-    100, 100,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -87,8 +77,10 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (big_trap,
+	    "Test oversize trapezoid with a clip region"
+	    "\nTest needs to be adjusted to trigger the original bug",
+	    "XFAIL trap", /* keywords */
+	    NULL, /* requirements */
+	    100, 100,
+	    NULL, draw)
diff --git a/test/bilevel-image.c b/test/bilevel-image.c
index 0af1d83..7435a2b 100644
--- a/test/bilevel-image.c
+++ b/test/bilevel-image.c
@@ -25,15 +25,6 @@
 
 #include "cairo-test.h"
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "bilevel-image",
-    "Test that PS can embed an RGB image with a bilevel alpha channel.",
-    12, 4,
-    draw
-};
-
 #define RGBx 0xffff0000, 0xff00ff00, 0xff0000ff, 0x00000000
 
 static cairo_test_status_t
@@ -62,8 +53,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (bilevel_image,
+	    "Test that PS can embed an RGB image with a bilevel alpha channel.",
+	    "alpha, ps", /* keywords */
+	    NULL, /* requirements */
+	    12, 4,
+	    NULL, draw)
diff --git a/test/bitmap-font.c b/test/bitmap-font.c
index 558ab79..e63b70c 100644
--- a/test/bitmap-font.c
+++ b/test/bitmap-font.c
@@ -36,16 +36,6 @@
 #define FONT "6x13.pcf"
 #define TEXT_SIZE 13
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "bitmap-font",
-    "Test drawing with a font consisting only of bitmaps"
-    "\nThe PDF and PS backends embed a slightly distorted font for the rotated case.",
-    246 + 1, 2 * TEXT_SIZE,
-    draw
-};
-
 static cairo_bool_t
 font_extents_equal (const cairo_font_extents_t *A,
 	            const cairo_font_extents_t *B)
@@ -215,8 +205,10 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (bitmap_font,
+	    "Test drawing with a font consisting only of bitmaps"
+	    "\nThe PDF and PS backends embed a slightly distorted font for the rotated case.",
+	    "text", /* keywords */
+	    "ft", /* requirements */
+	    246 + 1, 2 * TEXT_SIZE,
+	    NULL, draw)
diff --git a/test/cairo-test-private.h b/test/cairo-test-private.h
new file mode 100644
index 0000000..03c7a2b
--- /dev/null
+++ b/test/cairo-test-private.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright © 2004 Red Hat, Inc.
+ * Copyright © 2008 Chris Wilson
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of
+ * Red Hat, Inc. not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior
+ * permission. Red Hat, Inc. makes no representations about the
+ * suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * RED HAT, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL RED HAT, INC. BE LIABLE FOR ANY SPECIAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
+ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: Carl D. Worth <cworth at cworth.org>
+ *         Chris Wilson <chris at chris-wilson.co.uk>
+ */
+
+#ifndef _CAIRO_TEST_PRIVATE_H_
+#define _CAIRO_TEST_PRIVATE_H_
+
+#include "cairo-test.h"
+
+/* For communication between the core components of cairo-test and not
+ * for the tests themselves.
+ */
+
+CAIRO_BEGIN_DECLS
+
+cairo_bool_t
+cairo_test_target_has_similar (const cairo_test_context_t *ctx,
+			       const cairo_boilerplate_target_t *target);
+
+cairo_test_status_t
+_cairo_test_context_run (cairo_test_context_t *ctx);
+
+cairo_test_status_t
+_cairo_test_context_run_for_target (cairo_test_context_t *ctx,
+				    const cairo_boilerplate_target_t *target,
+				    cairo_bool_t similar,
+				    int dev_offset);
+
+void
+_cairo_test_context_init_for_test (cairo_test_context_t *ctx,
+				   const cairo_test_context_t *parent,
+				   const cairo_test_t *test);
+
+void
+cairo_test_init (cairo_test_context_t *ctx,
+		 const char *test_name);
+
+cairo_test_status_t
+cairo_test (const cairo_test_t *test);
+
+void
+cairo_test_fini (cairo_test_context_t *ctx);
+
+#if ! CAIRO_HAS_CONSTRUCTOR_ATTRIBUTE
+void
+_cairo_test_runner_register_tests (void);
+#endif
+
+CAIRO_END_DECLS
+
+#endif /* _CAIRO_TEST_PRIVATE_H_ */
diff --git a/test/cairo-test-runner.c b/test/cairo-test-runner.c
new file mode 100644
index 0000000..34a5725
--- /dev/null
+++ b/test/cairo-test-runner.c
@@ -0,0 +1,907 @@
+/*
+ * Copyright © 2008 Chris Wilson
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without
+ * fee, provided that the above copyright notice appear in all copies
+ * and that both that copyright notice and this permission notice
+ * appear in supporting documentation, and that the name of
+ * Chris Wilson not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior
+ * permission. Chris Wilson makes no representations about the
+ * suitability of this software for any purpose.  It is provided "as
+ * is" without express or implied warranty.
+ *
+ * CHRIS WILSON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL CHRIS WILSON BE LIABLE FOR ANY SPECIAL,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
+ * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: Chris Wilson <chris at chris-wilson.co.uk>
+ */
+
+#include "cairo-test-private.h"
+#include "cairo-boilerplate-getopt.h"
+
+/* get the "real" version info instead of dummy cairo-version.h */
+#undef CAIRO_VERSION_H
+#undef CAIRO_VERSION_MAJOR
+#undef CAIRO_VERSION_MINOR
+#undef CAIRO_VERSION_MICRO
+#include "../cairo-version.h"
+
+#include <pixman.h> /* for version information */
+
+#if HAVE_FORK && HAVE_WAITPID
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#if HAVE_SIGNAL_H
+#include <signal.h>
+#endif
+#include <sys/types.h>
+#include <sys/wait.h>
+#endif
+
+typedef struct _cairo_test_list {
+    const cairo_test_t *test;
+    struct _cairo_test_list *next;
+} cairo_test_list_t;
+
+typedef enum {
+    GE,
+    GT
+} cairo_test_compare_op_t;
+
+static cairo_test_list_t *tests;
+
+static void CAIRO_BOILERPLATE_PRINTF_FORMAT(2,3)
+_log (cairo_test_context_t *ctx,
+      const char *fmt,
+      ...)
+{
+    va_list ap;
+
+    va_start (ap, fmt);
+    vprintf (fmt, ap);
+    va_end (ap);
+
+    va_start (ap, fmt);
+    cairo_test_logv (ctx, fmt, ap);
+    va_end (ap);
+}
+
+static cairo_test_list_t *
+_list_prepend (cairo_test_list_t *head, const cairo_test_t *test)
+{
+    cairo_test_list_t *list;
+
+    list = xmalloc (sizeof (cairo_test_list_t));
+    list->test = test;
+    list->next = head;
+    head = list;
+
+    return head;
+}
+
+static cairo_test_list_t *
+_list_reverse (cairo_test_list_t *head)
+{
+    cairo_test_list_t *list, *next;
+
+    for (list = head, head = NULL; list != NULL; list = next) {
+	next = list->next;
+	list->next = head;
+	head = list;
+    }
+
+    return head;
+}
+
+static void
+_list_free (cairo_test_list_t *list)
+{
+    while (list != NULL) {
+	cairo_test_list_t *next = list->next;
+	free (list);
+	list = next;
+    }
+}
+
+#if HAVE_FORK && HAVE_WAITPID
+static cairo_test_status_t
+_cairo_test_wait (pid_t pid)
+{
+    int exitcode;
+
+    if (waitpid (pid, &exitcode, 0) != pid)
+	return CAIRO_TEST_CRASHED;
+
+    if (WIFSIGNALED (exitcode)) {
+	switch (WTERMSIG (exitcode)) {
+	case SIGINT:
+#if HAVE_RAISE
+	    raise (SIGINT);
+#endif
+	    return CAIRO_TEST_UNTESTED;
+	default:
+	    return CAIRO_TEST_CRASHED;
+	}
+    }
+
+    return WEXITSTATUS (exitcode);
+}
+#endif
+
+static cairo_test_status_t
+_cairo_test_runner_preamble (cairo_test_context_t *ctx)
+{
+#if HAVE_FORK && HAVE_WAITPID
+    pid_t pid;
+
+    switch ((pid = fork ())) {
+    case -1: /* error */
+	return CAIRO_TEST_UNTESTED;
+
+    case 0: /* child */
+	exit (ctx->test->preamble (ctx));
+
+    default:
+	return _cairo_test_wait (pid);
+    }
+#else
+    return ctx->test->preamble (ctx);
+#endif
+}
+
+static cairo_test_status_t
+_cairo_test_runner_draw (cairo_test_context_t *ctx,
+			 const cairo_boilerplate_target_t *target,
+			 cairo_bool_t similar,
+			 int device_offset)
+{
+#if HAVE_FORK && HAVE_WAITPID
+    pid_t pid;
+
+    switch ((pid = fork ())) {
+    case -1: /* error */
+	return CAIRO_TEST_UNTESTED;
+
+    case 0: /* child */
+	exit (_cairo_test_context_run_for_target (ctx, target,
+						  similar, device_offset));
+
+    default:
+	return _cairo_test_wait (pid);
+    }
+#else
+    return _cairo_test_context_run_for_target (ctx, target,
+					       similar, device_offset);
+#endif
+}
+
+static void
+append_argv (int *argc, char ***argv, const char *str)
+{
+    int old_argc;
+    char **old_argv;
+    cairo_bool_t doit;
+    const char *s, *t;
+    int olen;
+    int len;
+    int i;
+
+    if (str == NULL)
+	return;
+
+    old_argc = *argc;
+    old_argv = *argv;
+
+    doit = FALSE;
+    do {
+	if (doit)
+	    *argv = xmalloc (sizeof (char *) * (1 + *argc) + olen);
+
+	olen = sizeof (char *) * (1 + *argc);
+	for (i = 0; i < old_argc; i++) {
+	    len = strlen (old_argv[i]) + 1;
+	    if (doit) {
+		(*argv)[i] = (char *) *argv + olen;
+		memcpy ((*argv)[i], old_argv[i], len);
+	    }
+	    olen += len;
+	}
+
+	s = str;
+	while ((t = strpbrk (s, " \t,:;")) != NULL) {
+	    if (t - s) {
+		len = t - s;
+		if (doit) {
+		    (*argv)[i] = (char *) *argv + olen;
+		    memcpy ((*argv)[i], s, len);
+		    (*argv)[i][len] = '\0';
+		}
+		olen += len + 1;
+		i++;
+	    }
+	    s = t + 1;
+	}
+	if (*s != '\0') {
+	    len = strlen (s) + 1;
+	    if (doit) {
+		(*argv)[i] = (char *) *argv + olen;
+		memcpy ((*argv)[i], s, len);
+	    }
+	    olen += len;
+	    i++;
+	}
+    } while (doit++ == FALSE);
+    (*argv)[i] = NULL;
+    *argc += i;
+}
+
+typedef struct _cairo_test_runner {
+    cairo_test_context_t base;
+
+    unsigned int num_device_offsets;
+
+    int num_passed;
+    int num_xpassed;
+    int num_skipped;
+    int num_failed;
+    int num_xfailed;
+    int num_crashed;
+
+    cairo_test_list_t **crashes_per_target;
+    cairo_test_list_t **fails_per_target;
+    cairo_test_list_t **xpasses_per_target;
+
+    int *num_failed_per_target;
+    int *num_crashed_per_target;
+    int *num_xpassed_per_target;
+
+    cairo_bool_t list_only;
+    cairo_bool_t full_test;
+} cairo_test_runner_t;
+
+static void
+usage (const char *argv0)
+{
+    fprintf (stderr,
+	     "Usage: %s [-f] [test-names|keywords ...]\n"
+	     "       %s -l\n"
+	     "\n"
+	     "Run the cairo conformance test suite over the given tests (all by default)\n"
+	     "The command-line arguments are interpreted as follows:\n"
+	     "\n"
+	     "  -l	list only; just list selected test case names without executing\n"
+	     "  -f	full; run the full set of tests. By default the test suite\n"
+	     "          skips similar surface and device offset testing.\n"
+	     "\n"
+	     "If test names are given they are used as exact matches either to a specific\n"
+	     "test case or to a keyword, so a command such as\n"
+	     "\"cairo-test-suite text\" can be used to run all text test cases.\n",
+	     argv0, argv0);
+}
+
+static void
+_parse_cmdline (cairo_test_runner_t *runner, int *argc, char **argv[])
+{
+    int c;
+
+    while (1) {
+	c = _cairo_getopt (*argc, *argv, ":l");
+	if (c == -1)
+	    break;
+
+	switch (c) {
+	case 'l':
+	    runner->list_only = TRUE;
+	    break;
+	case 'f':
+	    runner->full_test = TRUE;
+	    break;
+	default:
+	    fprintf (stderr, "Internal error: unhandled option: %c\n", c);
+	    /* fall-through */
+	case '?':
+	    usage ((*argv)[0]);
+	    exit (1);
+	}
+    }
+
+    *argc -= optind;
+    *argv += optind;
+}
+
+static void
+_runner_init (cairo_test_runner_t *runner)
+{
+    cairo_test_init (&runner->base, "cairo-test-suite");
+
+    runner->xpasses_per_target = xcalloc (sizeof (cairo_test_list_t *),
+					  runner->base.num_targets);
+    runner->fails_per_target = xcalloc (sizeof (cairo_test_list_t *),
+					runner->base.num_targets);
+    runner->crashes_per_target = xcalloc (sizeof (cairo_test_list_t *),
+					  runner->base.num_targets);
+    runner->num_xpassed_per_target = xcalloc (sizeof (int),
+					      runner->base.num_targets);
+    runner->num_failed_per_target = xcalloc (sizeof (int),
+					     runner->base.num_targets);
+    runner->num_crashed_per_target = xcalloc (sizeof (int),
+					      runner->base.num_targets);
+}
+
+static void
+_runner_print_versions (cairo_test_runner_t *runner)
+{
+    _log (&runner->base,
+	 "Compiled against cairo %s, running on %s.\n",
+	 CAIRO_VERSION_STRING, cairo_version_string ());
+    _log (&runner->base,
+	 "Compiled against pixman %s, running on %s.\n",
+	 PIXMAN_VERSION_STRING, pixman_version_string ());
+
+    fflush (runner->base.log_file);
+}
+
+static void
+_runner_print_summary (cairo_test_runner_t *runner)
+{
+    _log (&runner->base,
+	  "%d Passed [%d unexpectedly], %d Failed [%d crashed, %d expected], %d Skipped\n",
+	  runner->num_passed + runner->num_xpassed,
+	  runner->num_xpassed,
+
+	  runner->num_failed + runner->num_crashed + runner->num_xfailed,
+	  runner->num_crashed,
+	  runner->num_xfailed,
+
+	  runner->num_skipped);
+}
+
+static void
+_runner_print_details (cairo_test_runner_t *runner)
+{
+    unsigned int n;
+
+    for (n = 0; n < runner->base.num_targets; n++) {
+	const cairo_boilerplate_target_t *target;
+	cairo_test_list_t *list;
+
+	target = runner->base.targets_to_test[n];
+	if (runner->num_crashed_per_target[n]) {
+	    _log (&runner->base, "%s (%s): %d crashed! -",
+		  target->name,
+		  cairo_boilerplate_content_name (target->content),
+		  runner->num_crashed_per_target[n]);
+
+	    for (list = runner->crashes_per_target[n];
+		 list != NULL;
+		 list = list->next)
+	    {
+		char *name = cairo_test_get_name (list->test);
+		_log (&runner->base, " %s", name);
+		free (name);
+	    }
+	    _log (&runner->base, "\n");
+	}
+
+	if (runner->num_failed_per_target[n]) {
+	    _log (&runner->base, "%s (%s): %d failed -",
+		  target->name,
+		  cairo_boilerplate_content_name (target->content),
+		  runner->num_failed_per_target[n]);
+
+	    for (list = runner->fails_per_target[n];
+		 list != NULL;
+		 list = list->next)
+	    {
+		char *name = cairo_test_get_name (list->test);
+		_log (&runner->base, " %s", name);
+		free (name);
+	    }
+	    _log (&runner->base, "\n");
+	}
+
+	if (runner->num_xpassed_per_target[n]) {
+	    _log (&runner->base, "%s (%s): %d unexpectedly passed -",
+		  target->name,
+		  cairo_boilerplate_content_name (target->content),
+		  runner->num_xpassed_per_target[n]);
+
+	    for (list = runner->xpasses_per_target[n];
+		 list != NULL;
+		 list = list->next)
+	    {
+		char *name = cairo_test_get_name (list->test);
+		_log (&runner->base, " %s", name);
+		free (name);
+	    }
+	    _log (&runner->base, "\n");
+	}
+    }
+}
+
+static void
+_runner_print_results (cairo_test_runner_t *runner)
+{
+    _runner_print_summary (runner);
+    _runner_print_details (runner);
+}
+
+static cairo_test_status_t
+_runner_fini (cairo_test_runner_t *runner)
+{
+    unsigned int n;
+
+    for (n = 0; n < runner->base.num_targets; n++) {
+	_list_free (runner->crashes_per_target[n]);
+	_list_free (runner->fails_per_target[n]);
+	_list_free (runner->xpasses_per_target[n]);
+    }
+    free (runner->crashes_per_target);
+    free (runner->fails_per_target);
+    free (runner->xpasses_per_target);
+
+    free (runner->num_crashed_per_target);
+    free (runner->num_failed_per_target);
+    free (runner->num_xpassed_per_target);
+
+    cairo_test_fini (&runner->base);
+
+    return runner->num_failed + runner->num_crashed ?
+	CAIRO_TEST_FAILURE :
+	runner->num_passed + runner->num_xpassed + runner->num_xfailed ?
+	CAIRO_TEST_SUCCESS : CAIRO_TEST_UNTESTED;
+}
+
+static cairo_bool_t
+_version_compare (int a, cairo_test_compare_op_t op, int b)
+{
+    switch (op) {
+    case GT: return a > b;
+    case GE: return a >= b;
+    default: return FALSE;
+    }
+}
+
+
+static cairo_bool_t
+_get_required_version (const char *str,
+		       cairo_test_compare_op_t *op,
+		       int *major,
+		       int *minor,
+		       int *micro)
+{
+    while (*str == ' ')
+	str++;
+
+    if (strncmp (str, ">=", 2) == 0) {
+	*op = GE;
+	str += 2;
+    } else if (strncmp (str, ">", 1) == 0) {
+	*op = GT;
+	str += 1;
+    } else
+	return FALSE;
+
+    while (*str == ' ')
+	str++;
+
+    if (sscanf (str, "%d.%d.%d", major, minor, micro) != 3) {
+	*micro = 0;
+	if (sscanf (str, "%d.%d", major, minor) != 2)
+	    return FALSE;
+    }
+
+    return TRUE;
+}
+
+static cairo_bool_t
+_has_required_cairo_version (const char *str)
+{
+    cairo_test_compare_op_t op;
+    int major, minor, micro;
+
+    if (! _get_required_version (str + 5 /* advance over "cairo" */,
+				 &op, &major, &minor, &micro))
+    {
+	fprintf (stderr, "unrecognised cairo version requirement '%s'\n", str);
+	return FALSE;
+    }
+
+    return _version_compare (cairo_version (),
+			     op,
+			     CAIRO_VERSION_ENCODE (major, minor, micro));
+}
+
+static cairo_bool_t
+_has_required_ghostscript_version (const char *str)
+{
+#if ! CAIRO_CAN_TEST_PS_SURFACE
+    return TRUE;
+#endif
+
+    str += 2; /* advance over "gs" */
+
+    return TRUE;
+}
+
+static cairo_bool_t
+_has_required_poppler_version (const char *str)
+{
+#if ! CAIRO_CAN_TEST_PDF_SURFACE
+    return TRUE;
+#endif
+
+    str += 7; /* advance over "poppler" */
+
+    return TRUE;
+}
+
+static cairo_bool_t
+_has_required_rsvg_version (const char *str)
+{
+#if ! CAIRO_CAN_TEST_SVG_SURFACE
+    return TRUE;
+#endif
+
+    str += 4; /* advance over "rsvg" */
+
+    return TRUE;
+}
+
+int
+main (int argc, char **argv)
+{
+    cairo_test_runner_t runner;
+    cairo_test_list_t *list;
+    cairo_test_status_t *target_status;
+    unsigned int n, m;
+    char targets[4096];
+    int len;
+
+#ifdef _MSC_VER
+    /* We don't want an assert dialog, we want stderr */
+    _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
+    _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
+#endif
+
+#ifndef CAIRO_HAS_CONSTRUCTOR_ATTRIBUTE
+    _cairo_test_runner_register_tests ();
+#endif
+
+    memset (&runner, 0, sizeof (runner));
+    runner.num_device_offsets = 1;
+
+    if (getenv ("CAIRO_TEST_MODE")) {
+	const char *env = getenv ("CAIRO_TEST_MODE");
+
+	if (strstr (env, "full")) {
+	    runner.full_test = TRUE;
+	}
+    }
+
+    _parse_cmdline (&runner, &argc, &argv);
+    append_argv (&argc, &argv, getenv ("CAIRO_TESTS"));
+
+    if (runner.full_test) {
+	runner.num_device_offsets = 2;
+    }
+
+    target_status = NULL; /* silence the compiler */
+    if (! runner.list_only) {
+	_runner_init (&runner);
+	_runner_print_versions (&runner);
+	target_status = xmalloc (sizeof (cairo_test_status_t) *
+				 runner.base.num_targets);
+    }
+
+    for (list = tests; list != NULL; list = list->next) {
+	cairo_test_context_t ctx;
+	cairo_test_status_t status, expectation;
+	cairo_bool_t failed = FALSE, crashed = FALSE, skipped = TRUE;
+	const char *XFAIL = NULL;
+	char *name = cairo_test_get_name (list->test);
+	int i;
+
+	/* check for restricted runs */
+	if (argc) {
+	    cairo_bool_t found = FALSE;
+	    const char *keywords = list->test->keywords;
+
+	    for (i = 0; i < argc; i++) {
+		const char *match = argv[i];
+		cairo_bool_t invert = match[0] == '!';
+		if (invert)
+		    match++;
+
+		/* exact match on test name */
+		if (strcmp (name, match) == 0) {
+		    found = ! invert;
+		    break;
+		} else if (invert) {
+		    found = TRUE;
+		}
+
+		/* keyword match */
+		if (keywords != NULL && strstr (keywords, match) != NULL) {
+		    found = ! invert;
+		    break;
+		} else if (invert) {
+		    found = TRUE;
+		}
+	    }
+
+	    if (! found) {
+		free (name);
+		continue;
+	    }
+	}
+
+	/* check to see if external requirements match */
+	if (list->test->requirements != NULL) {
+	    const char *requirements = list->test->requirements;
+	    const char *str;
+
+	    str = strstr (requirements, "cairo");
+	    if (str != NULL && ! _has_required_cairo_version (str)) {
+		if (runner.list_only)
+		    goto TEST_NEXT;
+		else
+		    goto TEST_SKIPPED;
+	    }
+
+	    str = strstr (requirements, "gs");
+	    if (str != NULL && ! _has_required_ghostscript_version (str)) {
+		if (runner.list_only)
+		    goto TEST_NEXT;
+		else
+		    goto TEST_SKIPPED;
+	    }
+
+	    str = strstr (requirements, "poppler");
+	    if (str != NULL && ! _has_required_poppler_version (str)) {
+		if (runner.list_only)
+		    goto TEST_NEXT;
+		else
+		    goto TEST_SKIPPED;
+	    }
+
+	    str = strstr (requirements, "rsvg");
+	    if (str != NULL && ! _has_required_rsvg_version (str)) {
+		if (runner.list_only)
+		    goto TEST_NEXT;
+		else
+		    goto TEST_SKIPPED;
+	    }
+	}
+
+	if (runner.list_only) {
+	    printf ("%s ", name);
+	    goto TEST_NEXT;
+	}
+
+	/* check for a failing test */
+	expectation = CAIRO_TEST_SUCCESS;
+	if (list->test->keywords != NULL &&
+	    (XFAIL = strstr (list->test->keywords, "XFAIL")) != NULL)
+	{
+	    if (XFAIL[5] == '=') {
+		/* backend specific expected failure */
+		XFAIL += 5;
+	    } else {
+		XFAIL = NULL;
+		expectation = CAIRO_TEST_FAILURE;
+	    }
+	}
+
+	_cairo_test_context_init_for_test (&ctx, &runner.base, list->test);
+	memset (target_status, 0,
+		sizeof (cairo_test_status_t) * ctx.num_targets);
+
+	if (ctx.test->preamble != NULL) {
+	    status = _cairo_test_runner_preamble (&ctx);
+	    switch (status) {
+	    case CAIRO_TEST_SUCCESS:
+		skipped = FALSE;
+		break;
+	    case CAIRO_TEST_NO_MEMORY:
+	    case CAIRO_TEST_FAILURE:
+		failed = TRUE;
+		goto TEST_DONE;
+	    case CAIRO_TEST_CRASHED:
+		failed = TRUE;
+		goto TEST_DONE;
+	    case CAIRO_TEST_UNTESTED:
+		goto TEST_DONE;
+	    }
+	}
+
+	if (ctx.test->draw == NULL)
+	    goto TEST_DONE;
+
+	for (n = 0; n < ctx.num_targets; n++) {
+	    const cairo_boilerplate_target_t *target;
+	    cairo_bool_t target_failed = FALSE,
+			 target_crashed = FALSE,
+			 target_skipped = TRUE;
+	    int has_similar;
+
+	    target = ctx.targets_to_test[n];
+
+	    if (XFAIL != NULL) {
+		const char *target_XFAIL, *base_XFAIL = NULL;
+
+		if (((target_XFAIL = strstr (XFAIL, target->name)) != NULL ||
+		     (base_XFAIL = target_XFAIL = strstr (XFAIL, target->basename)) != NULL) &&
+		    target_XFAIL < strpbrk (XFAIL, " \t;:") &&
+		    target_XFAIL[-1] != '!')
+		{
+		    ctx.expectation = CAIRO_TEST_FAILURE;
+
+		    if (base_XFAIL != NULL) {
+			unsigned slen;
+
+			slen = strpbrk (base_XFAIL, " \t;:,") - base_XFAIL;
+			if (slen != strlen (target->basename))
+			    ctx.expectation = CAIRO_TEST_SUCCESS;
+		    }
+		}
+		else
+		    ctx.expectation = CAIRO_TEST_SUCCESS;
+	    } else
+		ctx.expectation = expectation;
+
+	    has_similar = runner.full_test ?
+			  cairo_test_target_has_similar (&ctx, target) :
+		          0;
+	    for (m = 0; m < runner.num_device_offsets; m++) {
+		int dev_offset = m * 25;
+		int similar;
+
+		for (similar = 0; similar <= has_similar; similar++) {
+		    status = _cairo_test_runner_draw (&ctx, target,
+						      similar, dev_offset);
+		    switch (status) {
+		    case CAIRO_TEST_SUCCESS:
+			target_skipped = FALSE;
+			break;
+		    case CAIRO_TEST_NO_MEMORY:
+		    case CAIRO_TEST_FAILURE:
+			target_failed = TRUE;
+			break;
+		    case CAIRO_TEST_CRASHED:
+			target_crashed = TRUE;
+			break;
+		    case CAIRO_TEST_UNTESTED:
+			break;
+		    }
+		}
+	    }
+
+	    if (target_crashed) {
+		target_status[n] = CAIRO_TEST_CRASHED;
+		runner.num_crashed_per_target[n]++;
+		runner.crashes_per_target[n] = _list_prepend (runner.crashes_per_target[n],
+							      list->test);
+		crashed = TRUE;
+	    } else if (target_failed) {
+		if (ctx.expectation == CAIRO_TEST_SUCCESS) {
+		    target_status[n] = CAIRO_TEST_FAILURE;
+		    runner.num_failed_per_target[n]++;
+		    runner.fails_per_target[n] = _list_prepend (runner.fails_per_target[n],
+								list->test);
+		} else
+		    target_status[n] = CAIRO_TEST_SUCCESS;
+
+		failed = TRUE;
+	    } else if (target_skipped) {
+		target_status[n] = CAIRO_TEST_UNTESTED;
+	    } else {
+		target_status[n] = CAIRO_TEST_SUCCESS;
+		/* An unexpected pass should also be flagged */
+		if (ctx.expectation != CAIRO_TEST_SUCCESS) {
+		    target_status[n] = CAIRO_TEST_FAILURE;
+		    runner.num_xpassed_per_target[n]++;
+		    runner.xpasses_per_target[n] = _list_prepend (runner.xpasses_per_target[n],
+								  list->test);
+		}
+		skipped = FALSE;
+	    }
+	}
+
+  TEST_DONE:
+	cairo_test_fini (&ctx);
+  TEST_SKIPPED:
+	targets[0] = '\0';
+	if (crashed) {
+	    len = 0;
+	    for (n = 0 ; n < runner.base.num_targets; n++) {
+		if (target_status[n] == CAIRO_TEST_CRASHED) {
+		    if (strstr (targets,
+				runner.base.targets_to_test[n]->name) == NULL)
+		    {
+			len += snprintf (targets + len, sizeof (targets) - len,
+					 "%s, ",
+					 runner.base.targets_to_test[n]->name);
+		    }
+		}
+	    }
+	    targets[len-2] = '\0';
+	    _log (&runner.base, "\n%s: CRASH! (%s)\n", name, targets);
+	    runner.num_crashed++;
+	} else if (failed) {
+	    if (expectation == CAIRO_TEST_SUCCESS) {
+		len = 0;
+		for (n = 0 ; n < runner.base.num_targets; n++) {
+		    if (target_status[n] == CAIRO_TEST_FAILURE) {
+			if (strstr (targets,
+				    runner.base.targets_to_test[n]->name) == NULL)
+			{
+			    len += snprintf (targets + len,
+					     sizeof (targets) - len,
+					     "%s, ",
+					     runner.base.targets_to_test[n]->name);
+			}
+		    }
+		}
+		if (len == 0) {
+		    _log (&runner.base, "%s: XFAIL\n", name);
+		    runner.num_xfailed++;
+		} else {
+		    targets[len-2] = '\0';
+		    _log (&runner.base, "%s: FAIL (%s)\n", name, targets);
+		    runner.num_failed++;
+		}
+	    } else {
+		_log (&runner.base, "%s: XFAIL\n", name);
+		runner.num_xfailed++;
+	    }
+	} else if (skipped) {
+	    _log (&runner.base, "%s: UNTESTED\n", name);
+	    runner.num_skipped++;
+	} else {
+	    if (expectation == CAIRO_TEST_SUCCESS) {
+		_log (&runner.base, "%s: PASS\n", name);
+		runner.num_passed++;
+	    } else {
+		_log (&runner.base, "%s: XPASS\n", name);
+		runner.num_xpassed++;
+	    }
+	}
+	fflush (runner.base.log_file);
+
+  TEST_NEXT:
+	free (name);
+    }
+
+    _list_free (tests);
+
+    if (runner.list_only) {
+	printf ("\n");
+	return CAIRO_TEST_SUCCESS;
+    }
+
+    for (n = 0 ; n < runner.base.num_targets; n++) {
+	runner.crashes_per_target[n] = _list_reverse (runner.crashes_per_target[n]);
+	runner.fails_per_target[n] = _list_reverse (runner.fails_per_target[n]);
+	runner.xpasses_per_target[n] = _list_reverse (runner.xpasses_per_target[n]);
+    }
+
+    _runner_print_results (&runner);
+
+    free (target_status);
+    return _runner_fini (&runner);
+}
+
+void
+cairo_test_register (const cairo_test_t *test)
+{
+    tests = _list_prepend (tests, test);
+}
diff --git a/test/cairo-test.c b/test/cairo-test.c
index c2364a9..4802a18 100644
--- a/test/cairo-test.c
+++ b/test/cairo-test.c
@@ -1,5 +1,6 @@
 /*
  * Copyright © 2004 Red Hat, Inc.
+ * Copyright © 2008 Chris Wilson
  *
  * Permission to use, copy, modify, distribute, and sell this software
  * and its documentation for any purpose is hereby granted without
@@ -21,6 +22,7 @@
  * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  *
  * Author: Carl D. Worth <cworth at cworth.org>
+ *         Chris Wilson <chris at chris-wilson.co.uk>
  */
 
 #define _GNU_SOURCE 1	/* for feenableexcept() et al */
@@ -66,7 +68,7 @@
 #define MF(x)
 #endif
 
-#include "cairo-test.h"
+#include "cairo-test-private.h"
 
 #include "buffer-diff.h"
 
@@ -76,6 +78,7 @@
 #define access _access
 #define F_OK 0
 #endif
+
 #ifndef FALSE
 #define FALSE 0
 #endif
@@ -83,45 +86,45 @@
 #define TRUE !FALSE
 #endif
 
-static cairo_user_data_key_t _cairo_test_context_key;
+static const cairo_user_data_key_t _cairo_test_context_key;
 
 static void
 _xunlink (const cairo_test_context_t *ctx, const char *pathname);
 
-static const char *fail_face = "", *normal_face = "";
+static const char *fail_face = "", *xfail_face="", *normal_face = "";
+static cairo_bool_t print_fail_on_stdout;
 
 #define CAIRO_TEST_LOG_SUFFIX ".log"
 #define CAIRO_TEST_PNG_SUFFIX "-out.png"
 #define CAIRO_TEST_REF_SUFFIX "-ref.png"
 #define CAIRO_TEST_DIFF_SUFFIX "-diff.png"
+#define CAIRO_TEST_OUTPUT_DIR "output"
 
 #define NUM_DEVICE_OFFSETS 2
 
-static const char *vector_ignored_tests[] = {
-    /* We can't match the results of tests that depend on
-     * CAIRO_ANTIALIAS_NONE/SUBPIXEL for vector backends
-     * (nor do we care). */
-    /* XXX Perhaps this should be moved to a flag in cairo_test_t? */
-    "a1-image-sample",
-    "a1-traps-sample",
-    "ft-text-antialias-none",
-    "rectangle-rounding-error",
-    "text-antialias-gray",
-    "text-antialias-none",
-    "text-antialias-subpixel",
-    "text-lcd-filter-fir3",
-    "text-lcd-filter-fir5",
-    "text-lcd-filter-intra-pixel",
-    "text-lcd-filter-none",
-    "unantialiased-shapes",
-
-    /* Nor do we care about rendering anomalies in external renderers. */
-    "fill-degenerate-sort-order",
-    NULL
-};
+static char *
+_cairo_test_fixup_name (const char *original)
+{
+    int len = strlen (original);
+    char *name, *s;
+
+    name = xmalloc (len + 1);
+    s = memcpy (name, original, len + 1);
+    while ((s = strchr (s, '_')) != NULL)
+	*s++ = '-';
+
+    return name;
+}
+
+char *
+cairo_test_get_name (const cairo_test_t *test)
+{
+    return _cairo_test_fixup_name (test->name);
+}
 
 static void
 _cairo_test_init (cairo_test_context_t *ctx,
+		  const cairo_test_context_t *parent,
 		  const cairo_test_t *test,
 		  const char *test_name,
 		  cairo_test_status_t expectation)
@@ -135,7 +138,7 @@ _cairo_test_init (cairo_test_context_t *ctx,
 #endif
 
     ctx->test = test;
-    ctx->test_name = test_name;
+    ctx->test_name = _cairo_test_fixup_name (test_name);
     ctx->expectation = expectation;
 
     ctx->malloc_failure = 0;
@@ -146,7 +149,7 @@ _cairo_test_init (cairo_test_context_t *ctx,
 	ctx->malloc_failure = 0;
 #endif
 
-    xasprintf (&log_name, "%s%s", test_name, CAIRO_TEST_LOG_SUFFIX);
+    xasprintf (&log_name, "%s%s", ctx->test_name, CAIRO_TEST_LOG_SUFFIX);
     _xunlink (NULL, log_name);
 
     ctx->log_file = fopen (log_name, "a");
@@ -156,34 +159,62 @@ _cairo_test_init (cairo_test_context_t *ctx,
     }
     free (log_name);
 
-    ctx->srcdir = getenv ("srcdir");
-    if (ctx->srcdir == NULL)
-	ctx->srcdir = ".";
-
-    ctx->refdir = getenv ("CAIRO_REF_DIR");
-
     ctx->ref_name = NULL;
     ctx->ref_image = NULL;
     ctx->ref_image_flattened = NULL;
 
     ctx->thread = 0;
 
-    {
+    if (parent != NULL) {
+	ctx->targets_to_test = parent->targets_to_test;
+	ctx->num_targets = parent->num_targets;
+	ctx->limited_targets = parent->limited_targets;
+	ctx->own_targets = FALSE;
+
+	ctx->srcdir = parent->srcdir;
+	ctx->refdir = parent->refdir;
+    } else {
 	int tmp_num_targets;
 	cairo_bool_t tmp_limited_targets;
+
 	ctx->targets_to_test = cairo_boilerplate_get_targets (&tmp_num_targets, &tmp_limited_targets);
 	ctx->num_targets = tmp_num_targets;
 	ctx->limited_targets = tmp_limited_targets;
+	ctx->own_targets = TRUE;
+
+	ctx->srcdir = getenv ("srcdir");
+	if (ctx->srcdir == NULL)
+	    ctx->srcdir = ".";
+
+	ctx->refdir = getenv ("CAIRO_REF_DIR");
     }
 
-    printf ("\nTESTING %s\n", test_name);
+#ifdef HAVE_UNISTD_H
+    if (*fail_face == '\0' && isatty (2)) {
+	fail_face = "\033[41;37;1m";
+	xfail_face = "\033[33;1m";
+	normal_face = "\033[m";
+	if (isatty (1))
+	    print_fail_on_stdout = FALSE;
+    }
+#endif
+
+    printf ("\nTESTING %s\n", ctx->test_name);
+}
+
+void
+_cairo_test_context_init_for_test (cairo_test_context_t *ctx,
+				   const cairo_test_context_t *parent,
+				   const cairo_test_t *test)
+{
+    _cairo_test_init (ctx, parent, test, test->name, CAIRO_TEST_SUCCESS);
 }
 
 void
 cairo_test_init (cairo_test_context_t *ctx,
 		 const char *test_name)
 {
-    _cairo_test_init (ctx, NULL, test_name, CAIRO_TEST_SUCCESS);
+    _cairo_test_init (ctx, NULL, NULL, test_name, CAIRO_TEST_SUCCESS);
 }
 
 static void
@@ -215,7 +246,8 @@ cairo_test_fini (cairo_test_context_t *ctx)
     cairo_surface_destroy (ctx->ref_image);
     cairo_surface_destroy (ctx->ref_image_flattened);
 
-    cairo_boilerplate_free_targets (ctx->targets_to_test);
+    if (ctx->own_targets)
+	cairo_boilerplate_free_targets (ctx->targets_to_test);
 
     cairo_debug_reset_static_data ();
 #if HAVE_FCFINI
@@ -224,6 +256,14 @@ cairo_test_fini (cairo_test_context_t *ctx)
 }
 
 void
+cairo_test_logv (const cairo_test_context_t *ctx,
+	        const char *fmt, va_list va)
+{
+    FILE *file = ctx && ctx->log_file ? ctx->log_file : stderr;
+    vfprintf (file, fmt, va);
+}
+
+void
 cairo_test_log (const cairo_test_context_t *ctx, const char *fmt, ...)
 {
     va_list va;
@@ -347,7 +387,7 @@ done:
     return ref_name;
 }
 
-static cairo_bool_t
+cairo_bool_t
 cairo_test_target_has_similar (const cairo_test_context_t *ctx,
 			       const cairo_boilerplate_target_t *target)
 {
@@ -554,6 +594,24 @@ cairo_test_copy_file (const char *src_filename,
     return TRUE;
 }
 
+static cairo_bool_t
+_cairo_test_mkdir (const char *path)
+{
+#if ! HAVE_MKDIR
+    return FALSE;
+#elif HAVE_MKDIR == 1
+    if (mkdir (path) == 0)
+	return TRUE;
+#elif HAVE_MKDIR == 2
+    if (mkdir (path, 0770) == 0)
+	return TRUE;
+#else
+#error Bad value for HAVE_MKDIR
+#endif
+
+    return errno == EEXIST;
+}
+
 static cairo_test_status_t
 cairo_test_for_target (cairo_test_context_t		 *ctx,
 		       const cairo_boilerplate_target_t	 *target,
@@ -565,7 +623,8 @@ cairo_test_for_target (cairo_test_context_t		 *ctx,
     cairo_t *cr;
     const char *empty_str = "";
     char *offset_str, *thread_str;
-    char *base_name, *png_name, *ref_name, *diff_name;
+    char *base_name, *base_path;
+    char *png_path, *ref_path, *diff_path;
     char *test_filename = NULL, *pass_filename = NULL, *fail_filename = NULL;
     cairo_test_status_t ret;
     cairo_content_t expected_content;
@@ -576,6 +635,7 @@ cairo_test_for_target (cairo_test_context_t		 *ctx,
     int malloc_failure_iterations = ctx->malloc_failure;
     void *closure;
     int width, height;
+    cairo_bool_t have_output_dir;
     int last_fault_count = 0;
 
     /* Get the strings ready that we'll need. */
@@ -590,7 +650,7 @@ cairo_test_for_target (cairo_test_context_t		 *ctx,
 	thread_str = (char *) empty_str;
 
     xasprintf (&base_name, "%s-%s-%s%s%s%s",
-	       ctx->test->name,
+	       ctx->test_name,
 	       target->name,
 	       format,
 	       similar ? "-similar" : "",
@@ -603,23 +663,27 @@ cairo_test_for_target (cairo_test_context_t		 *ctx,
       free (thread_str);
 
 
-    ref_name = cairo_test_reference_image_filename (ctx,
+    ref_path = cairo_test_reference_image_filename (ctx,
 						    base_name,
-						    ctx->test->name,
+						    ctx->test_name,
 						    target->name,
 						    format);
-    xasprintf (&png_name,  "%s%s", base_name, CAIRO_TEST_PNG_SUFFIX);
-    xasprintf (&diff_name, "%s%s", base_name, CAIRO_TEST_DIFF_SUFFIX);
-
-    if (target->is_vector) {
-	int i;
-
-	for (i = 0; vector_ignored_tests[i] != NULL; i++)
-	    if (strcmp (ctx->test->name, vector_ignored_tests[i]) == 0) {
-		cairo_test_log (ctx, "Error: Skipping for vector target %s\n", target->name);
-		ret = CAIRO_TEST_UNTESTED;
-		goto UNWIND_STRINGS;
-	    }
+    have_output_dir = _cairo_test_mkdir (CAIRO_TEST_OUTPUT_DIR);
+    xasprintf (&base_path, "%s/%s",
+	       have_output_dir ? CAIRO_TEST_OUTPUT_DIR : ".",
+	       base_name);
+    xasprintf (&png_path, "%s" CAIRO_TEST_PNG_SUFFIX, base_path);
+    xasprintf (&diff_path, "%s" CAIRO_TEST_DIFF_SUFFIX, base_path);
+
+    if (ctx->test->requirements != NULL) {
+	const char *required = target->is_vector ? "target=raster" : "target=vector";
+	if (strstr (ctx->test->requirements, required) != NULL) {
+	    cairo_test_log (ctx, "Error: Skipping for %s target %s\n",
+			    target->is_vector ? "vector" : "raster",
+			    target->name);
+	    ret = CAIRO_TEST_UNTESTED;
+	    goto UNWIND_STRINGS;
+	}
     }
 
     width = ctx->test->width;
@@ -642,7 +706,7 @@ REPEAT:
 
     /* Run the actual drawing code. */
     ret = CAIRO_TEST_SUCCESS;
-    surface = (target->create_surface) (base_name,
+    surface = (target->create_surface) (base_path,
 					target->content,
 					width, height,
 					ctx->test->width + 25 * NUM_DEVICE_OFFSETS,
@@ -803,16 +867,16 @@ REPEAT:
 	    }
 	}
 
-	if (ref_name == NULL) {
+	if (ref_path == NULL) {
 	    cairo_test_log (ctx, "Error: Cannot find reference image for %s\n",
 			    base_name);
 
 	    /* we may be running this test to generate reference images */
-	    _xunlink (ctx, png_name);
+	    _xunlink (ctx, png_path);
 	    test_image = target->get_image_surface (surface, 0,
 		                                    ctx->test->width,
 						    ctx->test->height);
-	    diff_status = cairo_surface_write_to_png (test_image, png_name);
+	    diff_status = cairo_surface_write_to_png (test_image, png_path);
 	    if (diff_status) {
 		cairo_test_log (ctx,
 			        "Error: Failed to write output image: %s\n",
@@ -827,15 +891,15 @@ REPEAT:
 
 	if (target->file_extension != NULL) { /* compare vector surfaces */
 	    xasprintf (&test_filename, "%s-out%s",
-		       base_name, target->file_extension);
+		       base_path, target->file_extension);
 	    xasprintf (&pass_filename, "%s-pass%s",
-		       base_name, target->file_extension);
+		       base_path, target->file_extension);
 	    xasprintf (&fail_filename, "%s-fail%s",
-		       base_name, target->file_extension);
+		       base_path, target->file_extension);
 
-	    if (cairo_test_file_is_older (pass_filename, ref_name))
+	    if (cairo_test_file_is_older (pass_filename, ref_path))
 		_xunlink (ctx, pass_filename);
-	    if (cairo_test_file_is_older (fail_filename, ref_name))
+	    if (cairo_test_file_is_older (fail_filename, ref_path))
 		_xunlink (ctx, fail_filename);
 
 	    if (cairo_test_files_equal (test_filename, pass_filename)) {
@@ -866,8 +930,8 @@ REPEAT:
 	    goto UNWIND_CAIRO;
 	}
 
-	_xunlink (ctx, png_name);
-	diff_status = cairo_surface_write_to_png (test_image, png_name);
+	_xunlink (ctx, png_path);
+	diff_status = cairo_surface_write_to_png (test_image, png_path);
 	if (diff_status) {
 	    cairo_test_log (ctx, "Error: Failed to write output image: %s\n",
 			    cairo_status_to_string (diff_status));
@@ -879,14 +943,9 @@ REPEAT:
 
 	/* binary compare png files (no decompression) */
 	if (target->file_extension == NULL) {
-	    xasprintf (&test_filename, "%s", png_name);
-	    xasprintf (&pass_filename, "%s-pass.png", base_name);
-	    xasprintf (&fail_filename, "%s-fail.png", base_name);
-
-	    if (cairo_test_file_is_older (pass_filename, ref_name))
-		_xunlink (ctx, pass_filename);
-	    if (cairo_test_file_is_older (fail_filename, ref_name))
-		_xunlink (ctx, fail_filename);
+	    xasprintf (&test_filename, "%s", png_path);
+	    xasprintf (&pass_filename, "%s-pass.png", base_path);
+	    xasprintf (&fail_filename, "%s-fail.png", base_path);
 
 	    if (cairo_test_files_equal (test_filename, pass_filename)) {
 		/* identical output as last known PASS, pass */
@@ -895,7 +954,7 @@ REPEAT:
 		ret = CAIRO_TEST_SUCCESS;
 		goto UNWIND_CAIRO;
 	    }
-	    if (cairo_test_files_equal (png_name, ref_name)) {
+	    if (cairo_test_files_equal (png_path, ref_path)) {
 		/* identical output as reference image */
 		cairo_test_log (ctx, "PNG file exactly reference image.\n");
 		cairo_surface_destroy (test_image);
@@ -912,7 +971,7 @@ REPEAT:
 		goto UNWIND_CAIRO;
 	    }
 	} else {
-	    if (cairo_test_files_equal (png_name, ref_name)) {
+	    if (cairo_test_files_equal (png_path, ref_path)) {
 		cairo_test_log (ctx, "PNG file exactly matches reference image.\n");
 		cairo_surface_destroy (test_image);
 		ret = CAIRO_TEST_SUCCESS;
@@ -920,11 +979,11 @@ REPEAT:
 	    }
 	}
 
-	ref_image = cairo_test_get_reference_image (ctx, ref_name,
+	ref_image = cairo_test_get_reference_image (ctx, ref_path,
 						    target->content == CAIRO_TEST_CONTENT_COLOR_ALPHA_FLATTENED);
 	if (cairo_surface_status (ref_image)) {
 	    cairo_test_log (ctx, "Error: Cannot open reference image for %s: %s\n",
-			    ref_name,
+			    ref_path,
 			    cairo_status_to_string (cairo_surface_status (ref_image)));
 	    cairo_surface_destroy (ref_image);
 	    cairo_surface_destroy (test_image);
@@ -940,7 +999,7 @@ REPEAT:
 				  test_image, ref_image,
 				  diff_image,
 				  &result);
-	_xunlink (ctx, diff_name);
+	_xunlink (ctx, diff_path);
 	if (diff_status) {
 	    cairo_test_log (ctx, "Error: Failed to compare images: %s\n",
 			    cairo_status_to_string (diff_status));
@@ -951,7 +1010,7 @@ REPEAT:
 	{
 	    ret = CAIRO_TEST_FAILURE;
 
-	    diff_status = cairo_surface_write_to_png (diff_image, diff_name);
+	    diff_status = cairo_surface_write_to_png (diff_image, diff_path);
 	    if (diff_status) {
 		cairo_test_log (ctx, "Error: Failed to write differences image: %s\n",
 				cairo_status_to_string (diff_status));
@@ -1016,22 +1075,24 @@ UNWIND_SURFACE:
 
     if (ctx->thread == 0) {
 	if (have_output)
-	    cairo_test_log (ctx, "OUTPUT: %s\n", png_name);
+	    cairo_test_log (ctx, "OUTPUT: %s\n", png_path);
 
 	if (have_result) {
 	    cairo_test_log (ctx,
 		            "REFERENCE: %s\nDIFFERENCE: %s\n",
-			    ref_name, diff_name);
+			    ref_path, diff_path);
 	}
     }
 
 UNWIND_STRINGS:
-    if (png_name)
-      free (png_name);
-    if (ref_name)
-      free (ref_name);
-    if (diff_name)
-      free (diff_name);
+    if (png_path)
+      free (png_path);
+    if (ref_path)
+      free (ref_path);
+    if (diff_path)
+      free (diff_path);
+    if (base_path)
+      free (base_path);
     if (base_name)
       free (base_name);
 
@@ -1053,24 +1114,182 @@ segfault_handler (int signal)
 }
 #endif
 
-static cairo_test_status_t
-cairo_test_run (cairo_test_context_t *ctx)
+cairo_test_status_t
+_cairo_test_context_run_for_target (cairo_test_context_t *ctx,
+				    const cairo_boilerplate_target_t *target,
+				    cairo_bool_t similar,
+				    int dev_offset)
 {
-    /* we use volatile here to make sure values are not clobbered
-     * by longjmp */
-    volatile size_t i, j;
-    volatile cairo_bool_t print_fail_on_stdout = ctx->thread == 0;
-    volatile cairo_test_status_t status, ret;
+    cairo_test_status_t status;
 
-#if HAVE_UNISTD_H
-    if (ctx->thread == 0 && isatty (2)) {
-	fail_face = "\033[41m\033[37m\033[1m";
-	normal_face = "\033[m";
-	if (isatty (1))
-	    print_fail_on_stdout = FALSE;
+    if (similar && ! cairo_test_target_has_similar (ctx, target))
+	return CAIRO_TEST_UNTESTED;
+
+    cairo_test_log (ctx,
+		    "Testing %s with %s%s target (dev offset %d)\n",
+		    ctx->test_name,
+		    similar ? " (similar) " : "",
+		    target->name,
+		    dev_offset);
+
+    if (ctx->thread == 0) {
+	printf ("%s-%s-%s [%d]%s:\t", ctx->test_name, target->name,
+		cairo_boilerplate_content_name (target->content),
+		dev_offset,
+		similar ? " (similar)": "");
+	fflush (stdout);
     }
+
+#if defined(HAVE_SIGNAL_H) && defined(HAVE_SETJMP_H)
+    if (ctx->thread == 0) {
+	void (* volatile old_segfault_handler)(int);
+	void (* volatile old_sigpipe_handler)(int);
+	void (* volatile old_sigabrt_handler)(int);
+
+	/* Set up a checkpoint to get back to in case of segfaults. */
+#ifdef SIGSEGV
+	old_segfault_handler = signal (SIGSEGV, segfault_handler);
+#endif
+#ifdef SIGPIPE
+	old_sigpipe_handler = signal (SIGPIPE, segfault_handler);
+#endif
+#ifdef SIGABRT
+	old_sigabrt_handler = signal (SIGABRT, segfault_handler);
+#endif
+	if (0 == setjmp (jmpbuf))
+	    status = cairo_test_for_target (ctx, target, dev_offset, similar);
+	else
+	    status = CAIRO_TEST_CRASHED;
+#ifdef SIGSEGV
+	signal (SIGSEGV, old_segfault_handler);
+#endif
+#ifdef SIGPIPE
+	signal (SIGPIPE, old_sigpipe_handler);
+#endif
+#ifdef SIGABRT
+	signal (SIGABRT, old_sigabrt_handler);
+#endif
+    } else {
+	status = cairo_test_for_target (ctx, target, dev_offset, similar);
+    }
+#else
+    status = cairo_test_for_target (ctx, target, dev_offset, similar);
 #endif
 
+    if (ctx->thread == 0) {
+	cairo_test_log (ctx,
+		"TEST: %s TARGET: %s FORMAT: %s OFFSET: %d SIMILAR: %d RESULT: ",
+			ctx->test_name, target->name,
+			cairo_boilerplate_content_name (target->content),
+			dev_offset, similar);
+	switch (status) {
+	case CAIRO_TEST_SUCCESS:
+	    printf ("PASS\n");
+	    cairo_test_log (ctx, "PASS\n");
+	    break;
+	case CAIRO_TEST_UNTESTED:
+	    printf ("UNTESTED\n");
+	    cairo_test_log (ctx, "UNTESTED\n");
+	    break;
+	case CAIRO_TEST_CRASHED:
+	    if (print_fail_on_stdout && ctx->thread == 0) {
+		printf ("!!!CRASHED!!!\n");
+	    } else {
+		/* eat the test name */
+		printf ("\r");
+		fflush (stdout);
+	    }
+	    cairo_test_log (ctx, "CRASHED\n");
+	    fprintf (stderr, "%s-%s-%s [%d]%s:\t%s!!!CRASHED!!!%s\n",
+		     ctx->test_name, target->name,
+		     cairo_boilerplate_content_name (target->content), dev_offset, similar ? " (similar)" : "",
+		     fail_face, normal_face);
+	    break;
+	default:
+	case CAIRO_TEST_NO_MEMORY:
+	case CAIRO_TEST_FAILURE:
+	    if (ctx->expectation == CAIRO_TEST_FAILURE) {
+		if (print_fail_on_stdout && ctx->thread == 0) {
+		    printf ("XFAIL\n");
+		} else {
+		    /* eat the test name */
+		    printf ("\r");
+		    fflush (stdout);
+		}
+		fprintf (stderr, "%s-%s-%s [%d]%s:\t%sXFAIL%s\n",
+			 ctx->test_name, target->name,
+			 cairo_boilerplate_content_name (target->content), dev_offset, similar ? " (similar)" : "",
+			 xfail_face, normal_face);
+		cairo_test_log (ctx, "XFAIL\n");
+	    } else {
+		if (print_fail_on_stdout && ctx->thread == 0) {
+		    printf ("FAIL\n");
+		} else {
+		    /* eat the test name */
+		    printf ("\r");
+		    fflush (stdout);
+		}
+		fprintf (stderr, "%s-%s-%s [%d]%s:\t%sFAIL%s\n",
+			 ctx->test_name, target->name,
+			 cairo_boilerplate_content_name (target->content), dev_offset, similar ? " (similar)" : "",
+			 fail_face, normal_face);
+		cairo_test_log (ctx, "FAIL\n");
+	    }
+	    break;
+	}
+	fflush (stdout);
+    } else {
+#if _POSIX_THREAD_SAFE_FUNCTIONS
+	flockfile (stdout);
+#endif
+	printf ("%s-%s-%s %d [%d]:\t",
+		ctx->test_name, target->name,
+		cairo_boilerplate_content_name (target->content),
+		ctx->thread,
+		dev_offset);
+	switch (status) {
+	case CAIRO_TEST_SUCCESS:
+	    printf ("PASS\n");
+	    break;
+	case CAIRO_TEST_UNTESTED:
+	    printf ("UNTESTED\n");
+	    break;
+	case CAIRO_TEST_CRASHED:
+	    printf ("!!!CRASHED!!!\n");
+	    break;
+	default:
+	case CAIRO_TEST_NO_MEMORY:
+	case CAIRO_TEST_FAILURE:
+	    if (ctx->expectation == CAIRO_TEST_FAILURE) {
+		printf ("XFAIL\n");
+	    } else {
+		printf ("FAIL\n");
+	    }
+	    break;
+	}
+
+	fflush (stdout);
+#if _POSIX_THREAD_SAFE_FUNCTIONS
+	funlockfile (stdout);
+#endif
+    }
+
+    return status;
+}
+
+cairo_test_status_t
+_cairo_test_context_run (cairo_test_context_t *ctx)
+{
+    size_t i, j;
+    cairo_test_status_t ret;
+
+    ret = CAIRO_TEST_UNTESTED;
+    if (ctx->test->preamble != NULL)
+	ret = ctx->test->preamble (ctx);
+
+    if (ctx->test->draw == NULL)
+	return ret;
+
     /* The intended logic here is that we return overall SUCCESS
      * iff. there is at least one tested backend and that all tested
      * backends return SUCCESS, OR, there's backends were manually
@@ -1088,147 +1307,21 @@ cairo_test_run (cairo_test_context_t *ctx)
      *
      * Also, on a crash, run no further tests.
      */
-    status = ret = CAIRO_TEST_UNTESTED;
-    for (i = 0; i < ctx->num_targets && status != CAIRO_TEST_CRASHED; i++) {
-	const cairo_boilerplate_target_t * volatile target = ctx->targets_to_test[(i + ctx->thread) % ctx->num_targets];
+    for (i = 0; i < ctx->num_targets && ret != CAIRO_TEST_CRASHED; i++) {
+	const cairo_boilerplate_target_t *target = ctx->targets_to_test[(i + ctx->thread) % ctx->num_targets];
 
 	for (j = 0; j < NUM_DEVICE_OFFSETS; j++) {
-	    volatile int dev_offset = ((j + ctx->thread) % NUM_DEVICE_OFFSETS) * 25;
-	    volatile int similar, has_similar;
+	    int dev_offset = ((j + ctx->thread) % NUM_DEVICE_OFFSETS) * 25;
+	    int similar, has_similar;
 
 	    has_similar = cairo_test_target_has_similar (ctx, target);
 	    for (similar = 0; similar <= has_similar ; similar++) {
-		cairo_test_log (ctx, "Testing %s with %s%s target (dev offset %d)\n", ctx->test_name, similar ? " (similar) " : "", target->name, dev_offset);
-		if (ctx->thread == 0) {
-		    printf ("%s-%s-%s [%d]%s:\t", ctx->test->name, target->name,
-			    cairo_boilerplate_content_name (target->content),
-			    dev_offset,
-			    similar ? " (similar) ": "");
-		    fflush (stdout);
-		}
-
-#if defined(HAVE_SIGNAL_H) && defined(HAVE_SETJMP_H)
-		if (ctx->thread == 0 && ! RUNNING_ON_VALGRIND) {
-		    void (* volatile old_segfault_handler)(int);
-		    void (* volatile old_sigpipe_handler)(int);
-
-		    /* Set up a checkpoint to get back to in case of segfaults. */
-#ifdef SIGSEGV
-		    old_segfault_handler = signal (SIGSEGV, segfault_handler);
-#endif
-#ifdef SIGPIPE
-		    old_sigpipe_handler = signal (SIGPIPE, segfault_handler);
-#endif
-		    if (0 == setjmp (jmpbuf))
-			status = cairo_test_for_target (ctx, target, dev_offset, similar);
-		    else
-			status = CAIRO_TEST_CRASHED;
-#ifdef SIGSEGV
-		    signal (SIGSEGV, old_segfault_handler);
-#endif
-#ifdef SIGPIPE
-		    signal (SIGPIPE, old_sigpipe_handler);
-#endif
-		} else {
-		    status = cairo_test_for_target (ctx, target, dev_offset, similar);
-		}
-#else
-		status = cairo_test_for_target (ctx, target, dev_offset, similar);
-#endif
+		cairo_status_t status;
 
-		if (ctx->thread == 0) {
-		    cairo_test_log (ctx,
-			    "TEST: %s TARGET: %s FORMAT: %s OFFSET: %d SIMILAR: %d RESULT: ",
-				    ctx->test->name, target->name,
-				    cairo_boilerplate_content_name (target->content),
-				    dev_offset, similar);
-		    switch (status) {
-		    case CAIRO_TEST_SUCCESS:
-			printf ("PASS\n");
-			cairo_test_log (ctx, "PASS\n");
-			if (ret == CAIRO_TEST_UNTESTED)
-			    ret = CAIRO_TEST_SUCCESS;
-			break;
-		    case CAIRO_TEST_UNTESTED:
-			printf ("UNTESTED\n");
-			cairo_test_log (ctx, "UNTESTED\n");
-			break;
-		    case CAIRO_TEST_CRASHED:
-			if (print_fail_on_stdout) {
-			    printf ("!!!CRASHED!!!\n");
-			} else {
-			/* eat the test name */
-			printf ("\r");
-			fflush (stdout);
-			}
-			cairo_test_log (ctx, "CRASHED\n");
-			fprintf (stderr, "%s-%s-%s [%d]%s:\t%s!!!CRASHED!!!%s\n",
-				 ctx->test->name, target->name,
-				 cairo_boilerplate_content_name (target->content), dev_offset, similar ? " (similar)" : "",
-				 fail_face, normal_face);
-			ret = CAIRO_TEST_FAILURE;
-			break;
-		    default:
-		    case CAIRO_TEST_NO_MEMORY:
-		    case CAIRO_TEST_FAILURE:
-			if (ctx->expectation == CAIRO_TEST_FAILURE) {
-			    printf ("XFAIL\n");
-			    cairo_test_log (ctx, "XFAIL\n");
-			} else {
-			    if (print_fail_on_stdout) {
-				printf ("FAIL\n");
-			    } else {
-				/* eat the test name */
-				printf ("\r");
-				fflush (stdout);
-			    }
-			    fprintf (stderr, "%s-%s-%s [%d]%s:\t%sFAIL%s\n",
-				     ctx->test->name, target->name,
-				     cairo_boilerplate_content_name (target->content), dev_offset, similar ? " (similar)" : "",
-				     fail_face, normal_face);
-			    cairo_test_log (ctx, "FAIL\n");
-			}
-			ret = CAIRO_TEST_FAILURE;
-			break;
-		    }
-		    fflush (stdout);
-		} else {
-#if _POSIX_THREAD_SAFE_FUNCTIONS
-		    flockfile (stdout);
-#endif
-		    printf ("%s-%s-%s %d [%d]:\t",
-			    ctx->test->name, target->name,
-			    cairo_boilerplate_content_name (target->content),
-			    ctx->thread,
-			    dev_offset);
-		    switch (status) {
-		    case CAIRO_TEST_SUCCESS:
-			printf ("PASS\n");
-			break;
-		    case CAIRO_TEST_UNTESTED:
-			printf ("UNTESTED\n");
-			break;
-		    case CAIRO_TEST_CRASHED:
-			printf ("!!!CRASHED!!!\n");
-			ret = CAIRO_TEST_FAILURE;
-			break;
-		    default:
-		    case CAIRO_TEST_NO_MEMORY:
-		    case CAIRO_TEST_FAILURE:
-			if (ctx->expectation == CAIRO_TEST_FAILURE) {
-			    printf ("XFAIL\n");
-			} else {
-			    printf ("FAIL\n");
-			}
-			ret = CAIRO_TEST_FAILURE;
-			break;
-		    }
-
-		    fflush (stdout);
-#if _POSIX_THREAD_SAFE_FUNCTIONS
-		    funlockfile (stdout);
-#endif
-		}
+		status = _cairo_test_context_run_for_target (ctx, target,
+						    similar, dev_offset);
+		if (ret == CAIRO_TEST_UNTESTED)
+		    ret = status;
 	    }
 	}
     }
@@ -1252,7 +1345,7 @@ cairo_test_run_threaded (void *closure)
 
     cairo_test_init_thread (&ctx, arg->ctx, arg->id);
 
-    ret = cairo_test_run (&ctx);
+    ret = _cairo_test_context_run (&ctx);
 
     cairo_test_fini (&ctx);
 
@@ -1269,7 +1362,7 @@ cairo_test_expecting (const cairo_test_t *test,
     cairo_test_status_t ret = CAIRO_TEST_SUCCESS;
     size_t num_threads;
 
-    _cairo_test_init (&ctx, test, test->name, expectation);
+    _cairo_test_init (&ctx, NULL, test, test->name, expectation);
     printf ("%s\n", test->description);
 
     if (expectation == CAIRO_TEST_FAILURE)
@@ -1301,10 +1394,10 @@ cairo_test_expecting (const cairo_test_t *test,
 
     if (ret == CAIRO_TEST_SUCCESS)
 #endif
-	ret = cairo_test_run (&ctx);
+	ret = _cairo_test_context_run (&ctx);
 
     if (ret != CAIRO_TEST_SUCCESS)
-        printf ("Check %s%s out for more information.\n", test->name, CAIRO_TEST_LOG_SUFFIX);
+        printf ("Check %s%s out for more information.\n", ctx.test_name, CAIRO_TEST_LOG_SUFFIX);
 
     /* if the set of targets to test was limited using CAIRO_TEST_TARGET, we
      * behave slightly differently, to ensure that limiting the targets does
@@ -1328,34 +1421,13 @@ cairo_test_expecting (const cairo_test_t *test,
 cairo_test_status_t
 cairo_test (const cairo_test_t *test)
 {
-    cairo_test_status_t expectation = CAIRO_TEST_SUCCESS;
-    const char *xfails;
-
 #ifdef _MSC_VER
     /* We don't want an assert dialog, we want stderr */
     _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
     _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
 #endif
 
-    if ((xfails = getenv ("CAIRO_XFAIL_TESTS")) != NULL) {
-	while (*xfails) {
-	    const char *end = strpbrk (xfails, " \t\r\n;:,");
-	    if (!end)
-	        end = xfails + strlen (xfails);
-
-	    if (0 == strncmp (test->name, xfails, end - xfails) &&
-		'\0' == test->name[end - xfails]) {
-		expectation = CAIRO_TEST_FAILURE;
-		break;
-	    }
-
-	    if (*end)
-	      end++;
-	    xfails = end;
-	}
-    }
-
-    return cairo_test_expecting (test, expectation);
+    return cairo_test_expecting (test, CAIRO_TEST_SUCCESS);
 }
 
 const cairo_test_context_t *
diff --git a/test/cairo-test.h b/test/cairo-test.h
index 2571071..f1b57cc 100644
--- a/test/cairo-test.h
+++ b/test/cairo-test.h
@@ -29,6 +29,8 @@
 #define CAIRO_BOILERPLATE_LOG(...) cairo_test_log (__VA_ARGS__)
 #include "cairo-boilerplate.h"
 
+#include <stdarg.h>
+
 CAIRO_BEGIN_DECLS
 
 #if   HAVE_STDINT_H
@@ -70,31 +72,42 @@ typedef enum cairo_test_status {
 typedef struct _cairo_test_context cairo_test_context_t;
 typedef struct _cairo_test cairo_test_t;
 
-typedef cairo_test_status_t  (cairo_test_draw_function_t) (cairo_t *cr, int width, int height);
+typedef cairo_test_status_t
+(cairo_test_preamble_function_t) (cairo_test_context_t *ctx);
+
+typedef cairo_test_status_t
+(cairo_test_draw_function_t) (cairo_t *cr, int width, int height);
 
 struct _cairo_test {
     const char *name;
     const char *description;
+    const char *keywords;
+    const char *requirements;
     int width;
     int height;
+    cairo_test_preamble_function_t *preamble;
     cairo_test_draw_function_t *draw;
 };
 
 /* The standard test interface which works by examining result image.
  *
- * cairo_test() accepts a test struct which will be called once for
- * each testable backend. The following checks will be performed for
- * each backend:
+ * CAIRO_TEST() constructs a test which will be called once before (the
+ * preamble callback), and then once for each testable backend (the draw
+ * callback). The following checks will be performed for each backend:
+ *
+ * 1) If preamble() returns CAIRO_TEST_UNTESTED, the test is skipped.
  *
- * 1) If draw() does not return CAIRO_TEST_SUCCESS then this backend
+ * 2) If preamble() does not return CAIRO_TEST_SUCCESS, the test fails.
+ *
+ * 3) If draw() does not return CAIRO_TEST_SUCCESS then this backend
  *    fails.
  *
- * 2) Otherwise, if cairo_status(cr) indicates an error then this
+ * 4) Otherwise, if cairo_status(cr) indicates an error then this
  *    backend fails.
  *
- * 3) Otherwise, if the image size is 0, then this backend passes.
+ * 5) Otherwise, if the image size is 0, then this backend passes.
  *
- * 4) Otherwise, if every channel of every pixel exactly matches the
+ * 6) Otherwise, if every channel of every pixel exactly matches the
  *    reference image then this backend passes. If not, this backend
  *    fails.
  *
@@ -102,15 +115,44 @@ struct _cairo_test {
  * one backend that is tested and if all tested backend pass according
  * to the four criteria above.
  */
-cairo_test_status_t
-cairo_test (const cairo_test_t *test);
+#if CAIRO_HAS_CONSTRUCTOR_ATTRIBUTE
+#define CAIRO_TEST(name, description, keywords, requirements, width, height, preamble, draw) \
+static void __attribute__((constructor)) _register_##name (void) \
+{\
+    static const cairo_test_t test = { \
+	#name, description, \
+	keywords, requirements, \
+	width, height, \
+	preamble, draw \
+    }; \
+    cairo_test_register (&test); \
+}
+#else
+#define CAIRO_TEST(name, description, keywords, requirements, width, height, preamble, draw) \
+void _register_##name (void); \
+void _register_##name (void) { \
+    static const cairo_test_t test = { \
+	#name, description, \
+	keywords, requirements, \
+	width, height, \
+	preamble, draw \
+    }; \
+    cairo_test_register (&test); \
+}
+#endif
+
+void
+cairo_test_register (const cairo_test_t *test);
 
 /* The full context for the test.
- * For ordinary tests (using cairo_test()) the context is passed to the draw
- * routine via user_data on the cairo_t.  The reason why the context is not
- * passed as an explicit parameter is that it is rarely required by the test
- * itself and by removing the parameter we can keep the draw routines simple
- * and serve as example code.
+ * For ordinary tests (using the CAIRO_TEST()->draw interface) the context
+ * is passed to the draw routine via user_data on the cairo_t.
+ * The reason why the context is not passed as an explicit parameter is that
+ * it is rarely required by the test itself and by removing the parameter
+ * we can keep the draw routines simple and serve as example code.
+ *
+ * In contrast, for the preamble phase the context is passed as the only
+ * parameter.
  */
 struct _cairo_test_context {
     const cairo_test_t *test;
@@ -128,6 +170,7 @@ struct _cairo_test_context {
     size_t num_targets;
     cairo_bool_t limited_targets;
     cairo_boilerplate_target_t **targets_to_test;
+    cairo_bool_t own_targets;
 
     int malloc_failure;
     int last_fault_count;
@@ -140,35 +183,20 @@ const cairo_test_context_t *
 cairo_test_get_context (cairo_t *cr);
 
 
-/* cairo_test_init(), cairo_test_log(), and cairo_test_fini() exist to
- * help in writing tests for which cairo_test() is not appropriate for
- * one reason or another. For example, some tests might not be doing
- * any drawing at all, or may need to create their own cairo_t rather
- * than be handed one by cairo_test.
- */
-
-
-/* Initialize test-specific resources, (log files, etc.) */
-void
-cairo_test_init (cairo_test_context_t *ctx,
-		 const char *test_name);
-
-/* Finalize test-specific resource. */
-void
-cairo_test_fini (cairo_test_context_t *ctx);
-
-
 /* Print a message to the log file, ala printf. */
 void
 cairo_test_log (const cairo_test_context_t *ctx,
 	        const char *fmt, ...) CAIRO_BOILERPLATE_PRINTF_FORMAT(2, 3);
+void
+cairo_test_logv (const cairo_test_context_t *ctx,
+	        const char *fmt, va_list ap) CAIRO_BOILERPLATE_PRINTF_FORMAT(2, 0);
 
 void
 cairo_test_log_path (const cairo_test_context_t *ctx,
 		     const cairo_path_t *path);
 
 /* Helper functions that take care of finding source images even when
- * building in a non-srcdir manner, (ie. the tests will be run in a
+ * building in a non-srcdir manner, (i.e. the tests will be run in a
  * directory that is different from the one where the source image
  * exists). */
 cairo_surface_t *
@@ -188,6 +216,9 @@ cairo_bool_t
 cairo_test_is_target_enabled (const cairo_test_context_t *ctx,
 	                      const char *target);
 
+char *
+cairo_test_get_name (const cairo_test_t *test);
+
 cairo_bool_t
 cairo_test_malloc_failure (const cairo_test_context_t *ctx,
 	                   cairo_status_t status);
diff --git a/test/caps-joins-alpha.c b/test/caps-joins-alpha.c
index 7595095..bbff44e 100644
--- a/test/caps-joins-alpha.c
+++ b/test/caps-joins-alpha.c
@@ -26,20 +26,10 @@
 
 #include "cairo-test.h"
 
-#define LINE_WIDTH 	10.
-#define SIZE 		(5 * LINE_WIDTH)
+#define LINE_WIDTH	10.
+#define SIZE		(5 * LINE_WIDTH)
 #define PAD		(2 * LINE_WIDTH)
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "caps-joins-alpha",
-    "Test caps and joins with some source alpha",
-    3 * (PAD + SIZE) + PAD,
-    PAD + SIZE + PAD,
-    draw
-};
-
 static void
 make_path (cairo_t *cr)
 {
@@ -90,8 +80,10 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (caps_joins_alpha,
+	    "Test caps and joins with some source alpha",
+	    "stroke", /* keywords */
+	    NULL, /* requirements */
+	    3 * (PAD + SIZE) + PAD,
+	    PAD + SIZE + PAD,
+	    NULL, draw)
diff --git a/test/caps-joins.c b/test/caps-joins.c
index bbda047..5ec6a81 100644
--- a/test/caps-joins.c
+++ b/test/caps-joins.c
@@ -25,20 +25,10 @@
 
 #include "cairo-test.h"
 
-#define LINE_WIDTH 	10.
-#define SIZE 		(5 * LINE_WIDTH)
+#define LINE_WIDTH	10.
+#define SIZE		(5 * LINE_WIDTH)
 #define PAD		(2 * LINE_WIDTH)
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "caps-joins",
-    "Test caps and joins",
-    3 * (PAD + SIZE) + PAD,
-    PAD + SIZE + PAD,
-    draw
-};
-
 static void
 make_path (cairo_t *cr)
 {
@@ -87,8 +77,11 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (caps_joins,
+	    "Test caps and joins",
+	    "stroke", /* keywords */
+	    NULL, /* requirements */
+	    3 * (PAD + SIZE) + PAD,
+	    PAD + SIZE + PAD,
+	    NULL, draw)
+
diff --git a/test/caps-sub-paths.c b/test/caps-sub-paths.c
index e431576..2310eb7 100644
--- a/test/caps-sub-paths.c
+++ b/test/caps-sub-paths.c
@@ -30,15 +30,6 @@
    https://bugs.freedesktop.org/show_bug.cgi?id=4205
 */
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "caps-sub-paths",
-    "Test that sub-paths receive caps.",
-    20, 20,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -65,8 +56,10 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (caps_sub_paths,
+	    "Test that sub-paths receive caps.",
+	    "stroke", /* keywords */
+	    NULL, /* requirements */
+	    20, 20,
+	    NULL, draw)
+
diff --git a/test/clip-all.c b/test/clip-all.c
index 7e08b8e..3e7d24e 100644
--- a/test/clip-all.c
+++ b/test/clip-all.c
@@ -28,15 +28,6 @@
 #define SIZE 10
 #define CLIP_SIZE 2
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "clip-all",
-    "Test clipping with everything clipped out",
-    SIZE, SIZE,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -75,8 +66,10 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (clip_all,
+	    "Test clipping with everything clipped out",
+	    "clip", /* keywords */
+	    NULL, /* requirements */
+	    SIZE, SIZE,
+	    NULL, draw)
+
diff --git a/test/clip-empty.c b/test/clip-empty.c
index 2635042..f6848e5 100644
--- a/test/clip-empty.c
+++ b/test/clip-empty.c
@@ -27,15 +27,6 @@
 
 #define SIZE 10
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "clip-empty",
-    "Test clipping with an empty clip path",
-    SIZE, SIZE,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -65,8 +56,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (clip_empty,
+	    "Test clipping with an empty clip path",
+	    "clip", /* keywords */
+	    NULL, /* requirements */
+	    SIZE, SIZE,
+	    NULL, draw)
diff --git a/test/clip-fill-rule-pixel-aligned.c b/test/clip-fill-rule-pixel-aligned.c
index db7f66f..210afcb 100644
--- a/test/clip-fill-rule-pixel-aligned.c
+++ b/test/clip-fill-rule-pixel-aligned.c
@@ -28,16 +28,6 @@
 #define PAD 1
 #define SIZE 5
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "clip-fill-rule-pixel-aligned",
-    "Tests interaction of clipping and cairo_set_fill_rule with a pixel-aligned path",
-    PAD + (SIZE*4) + PAD + (SIZE*4) + PAD,
-    PAD + (SIZE*4) + PAD,
-    draw
-};
-
 static void
 pixel_aligned_path (cairo_t *cr)
 {
@@ -91,8 +81,10 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (clip_fill_rule_pixel_aligned,
+	    "Tests interaction of clipping and cairo_set_fill_rule with a pixel-aligned path",
+	    "clip", /* keywords */
+	    NULL, /* requirements */
+	    PAD + (SIZE*4) + PAD + (SIZE*4) + PAD,
+	    PAD + (SIZE*4) + PAD,
+	    NULL, draw)
diff --git a/test/clip-fill-rule.c b/test/clip-fill-rule.c
index 7140bc5..8351d86 100644
--- a/test/clip-fill-rule.c
+++ b/test/clip-fill-rule.c
@@ -27,15 +27,6 @@
 
 #define STAR_SIZE 20
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "clip-fill-rule",
-    "Tests interaction of clipping with cairo_set_fill_rule",
-    STAR_SIZE * 2 + 2, STAR_SIZE + 2,
-    draw
-};
-
 static void
 star_path (cairo_t *cr)
 {
@@ -75,8 +66,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (clip_fill_rule,
+	    "Tests interaction of clipping with cairo_set_fill_rule",
+	    "clip", /* keywords */
+	    NULL, /* requirements */
+	    STAR_SIZE * 2 + 2, STAR_SIZE + 2,
+	    NULL, draw)
diff --git a/test/clip-nesting.c b/test/clip-nesting.c
index e82e817..a73ac99 100644
--- a/test/clip-nesting.c
+++ b/test/clip-nesting.c
@@ -31,15 +31,6 @@
 #define BORDER 10
 #define LINE_WIDTH 20
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "clip-nesting",
-    "Test clipping with multiple contexts for the same surface",
-    SIZE, SIZE,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -94,8 +85,9 @@ draw (cairo_t *cr, int width, int height)
 
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (clip_nesting,
+	    "Test clipping with multiple contexts for the same surface",
+	    "clip", /* keywords */
+	    NULL, /* requirements */
+	    SIZE, SIZE,
+	    NULL, draw)
diff --git a/test/clip-operator.c b/test/clip-operator.c
index 3c4bcbb..d9ffcd2 100644
--- a/test/clip-operator.c
+++ b/test/clip-operator.c
@@ -126,15 +126,6 @@ static void (* const draw_funcs[])(cairo_t *cr, int x, int y) = {
 #define IMAGE_WIDTH (N_OPERATORS * (WIDTH + PAD) + PAD)
 #define IMAGE_HEIGHT (ARRAY_SIZE (draw_funcs) * (HEIGHT + PAD) + PAD)
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "clip-operator",
-    "Surface clipping with different operators",
-    IMAGE_WIDTH, IMAGE_HEIGHT,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -189,8 +180,10 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (clip_operator,
+	    "Surface clipping with different operators",
+	    "XFAIL=svg12 clip", /* keywords */
+	    NULL, /* requirements */
+	    IMAGE_WIDTH, IMAGE_HEIGHT,
+	    NULL, draw)
+
diff --git a/test/clip-push-group.c b/test/clip-push-group.c
index 66027b4..4effb0a 100644
--- a/test/clip-push-group.c
+++ b/test/clip-push-group.c
@@ -36,15 +36,6 @@
 #define SIZE 10
 #define PAD 2
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "clip-push-group",
-    "Test that push_group doesn't crash after setting a surface-based clip",
-    SIZE, SIZE,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -68,8 +59,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (clip_push_group,
+	    "Test that push_group doesn't crash after setting a surface-based clip",
+	    "clip", /* keywords */
+	    NULL, /* requirements */
+	    SIZE, SIZE,
+	    NULL, draw)
diff --git a/test/clip-twice.c b/test/clip-twice.c
index 435b0c5..641b551 100644
--- a/test/clip-twice.c
+++ b/test/clip-twice.c
@@ -28,15 +28,6 @@
 #define WIDTH 64
 #define HEIGHT 64
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "clip-twice",
-    "Verifies that the clip mask is updated correctly when it constructed by setting the clip path twice.",
-    WIDTH, HEIGHT,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -75,8 +66,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (clip_twice,
+	    "Verifies that the clip mask is updated correctly when it constructed by setting the clip path twice.",
+	    "clip", /* keywords */
+	    NULL, /* requirements */
+	    WIDTH, HEIGHT,
+	    NULL, draw)
diff --git a/test/clip-zero.c b/test/clip-zero.c
index 4482c16..5afd1b5 100644
--- a/test/clip-zero.c
+++ b/test/clip-zero.c
@@ -26,15 +26,6 @@
 
 #include "cairo-test.h"
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "clip-zero",
-    "Verifies that 0x0 surfaces or clips don't cause problems.",
-    0, 0,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -73,8 +64,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (clip_zero,
+	    "Verifies that 0x0 surfaces or clips don't cause problems.",
+	    "clip", /* keywords */
+	    NULL, /* requirements */
+	    0, 0,
+	    NULL, draw)
diff --git a/test/clipped-group.c b/test/clipped-group.c
index e1f68be..a66f357 100644
--- a/test/clipped-group.c
+++ b/test/clipped-group.c
@@ -28,15 +28,6 @@
 #define WIDTH 60
 #define HEIGHT 70
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "clipped-group",
-    "Test that a clipped group ends up in the right place",
-    WIDTH, HEIGHT,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -89,8 +80,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (clipped_group,
+	    "Test that a clipped group ends up in the right place",
+	    "clip", /* keywords */
+	    NULL, /* requirements */
+	    WIDTH, HEIGHT,
+	    NULL, draw)
diff --git a/test/clipped-surface.c b/test/clipped-surface.c
index 0fa69a1..a10652d 100644
--- a/test/clipped-surface.c
+++ b/test/clipped-surface.c
@@ -31,14 +31,6 @@
 #include "cairo-test.h"
 
 static const char png_filename[] = "romedalen.png";
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "clipped-surface",
-    "Tests application of a clip to a source surface",
-    40, 40,
-    draw
-};
 
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
@@ -63,8 +55,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (clipped_surface,
+	    "Tests application of a clip to a source surface",
+	    "clip", /* keywords */
+	    NULL, /* requirements */
+	    40, 40,
+	    NULL, draw)
diff --git a/test/close-path.c b/test/close-path.c
index 999fb37..41b237e 100644
--- a/test/close-path.c
+++ b/test/close-path.c
@@ -28,13 +28,6 @@
 
 static cairo_test_draw_function_t draw;
 
-static const cairo_test_t test = {
-    "close-path",
-    "Test some corner cases related to cairo_close_path",
-    32, 16,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -77,8 +70,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (close_path,
+	    "Test some corner cases related to cairo_close_path",
+	    "path", /* keywords */
+	    NULL, /* requirements */
+	    32, 16,
+	    NULL, draw)
diff --git a/test/composite-integer-translate-over-repeat.c b/test/composite-integer-translate-over-repeat.c
index 3e9d314..9a60d9a 100644
--- a/test/composite-integer-translate-over-repeat.c
+++ b/test/composite-integer-translate-over-repeat.c
@@ -32,15 +32,6 @@
 #define SIZE2 20
 #define OFFSET 10
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "composite-integer-translate-over-repeat",
-    "Test simple compositing: integer-translation 32->32 OVER, with repeat",
-    SIZE, SIZE,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -85,8 +76,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (composite_integer_translate_over_repeat,
+	    "Test simple compositing: integer-translation 32->32 OVER, with repeat",
+	    "composite", /* keywords */
+	    NULL, /* requirements */
+	    SIZE, SIZE,
+	    NULL, draw)
diff --git a/test/composite-integer-translate-over.c b/test/composite-integer-translate-over.c
index 835a4dc..8c6b9c2 100644
--- a/test/composite-integer-translate-over.c
+++ b/test/composite-integer-translate-over.c
@@ -28,16 +28,7 @@
 
 #define SIZE 100
 #define OFFSET 10
-const char	png_filename[]	= "romedalen.png";
-
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "composite-integer-translate-over",
-    "Test simple compositing: integer-translation 32->32 OVER",
-    SIZE, SIZE,
-    draw
-};
+static const char *png_filename = "romedalen.png";
 
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
@@ -62,8 +53,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (composite_integer_translate_over,
+	    "Test simple compositing: integer-translation 32->32 OVER",
+	    "composite", /* keywords */
+	    NULL, /* requirements */
+	    SIZE, SIZE,
+	    NULL, draw)
diff --git a/test/composite-integer-translate-source.c b/test/composite-integer-translate-source.c
index 0945cc1..9b6b749 100644
--- a/test/composite-integer-translate-source.c
+++ b/test/composite-integer-translate-source.c
@@ -31,16 +31,7 @@
 #define SIZE 100
 #define OFFSET 10
 
-const char	png_filename[]	= "romedalen.png";
-
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "composite-integer-translate-source",
-    "Test simple compositing: integer-translation 32->32 SOURCE",
-    SIZE, SIZE,
-    draw
-};
+static const char *png_filename = "romedalen.png";
 
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
@@ -65,8 +56,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (composite_integer_translate_source,
+	    "Test simple compositing: integer-translation 32->32 SOURCE",
+	    "XFAIL=svg12 composite", /* keywords */
+	    NULL, /* requirements */
+	    SIZE, SIZE,
+	    NULL, draw)
diff --git a/test/copy-path.c b/test/copy-path.c
index dfc671d..5b54c84 100644
--- a/test/copy-path.c
+++ b/test/copy-path.c
@@ -26,15 +26,6 @@
 #include <stdlib.h>
 #include "cairo-test.h"
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "copy-path",
-    "Tests calls to path_data functions: cairo_copy_path, cairo_copy_path_flat, and cairo_append_path",
-    45, 53,
-    draw
-};
-
 static void
 scale_by_two (double *x, double *y)
 {
@@ -200,18 +191,15 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
+static cairo_test_status_t
+preamble (cairo_test_context_t *ctx)
 {
-    cairo_test_context_t ctx;
     cairo_t *cr;
     cairo_path_data_t data;
     cairo_path_t path;
     cairo_surface_t *surface;
     cairo_status_t status;
 
-    cairo_test_init (&ctx, "copy-path");
-
     surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 1, 1);
 
     /* Test a few error cases for cairo_append_path_data */
@@ -221,7 +209,6 @@ main (void)
     cairo_destroy (cr);
     if (status != CAIRO_STATUS_NULL_POINTER) {
 	cairo_surface_destroy (surface);
-	cairo_test_fini (&ctx);
 	return CAIRO_TEST_FAILURE;
     }
 
@@ -232,7 +219,6 @@ main (void)
     cairo_destroy (cr);
     if (status != CAIRO_STATUS_INVALID_STATUS) {
 	cairo_surface_destroy (surface);
-	cairo_test_fini (&ctx);
 	return CAIRO_TEST_FAILURE;
     }
 
@@ -243,7 +229,6 @@ main (void)
     cairo_destroy (cr);
     if (status != CAIRO_STATUS_NO_MEMORY) {
 	cairo_surface_destroy (surface);
-	cairo_test_fini (&ctx);
 	return CAIRO_TEST_FAILURE;
     }
 
@@ -256,7 +241,6 @@ main (void)
     cairo_destroy (cr);
     if (status != CAIRO_STATUS_SUCCESS) {
 	cairo_surface_destroy (surface);
-	cairo_test_fini (&ctx);
 	return CAIRO_TEST_FAILURE;
     }
 
@@ -269,7 +253,6 @@ main (void)
     cairo_destroy (cr);
     if (status != CAIRO_STATUS_NULL_POINTER) {
 	cairo_surface_destroy (surface);
-	cairo_test_fini (&ctx);
 	return CAIRO_TEST_FAILURE;
     }
 
@@ -284,7 +267,6 @@ main (void)
     cairo_destroy (cr);
     if (status != CAIRO_STATUS_INVALID_PATH_DATA) {
 	cairo_surface_destroy (surface);
-	cairo_test_fini (&ctx);
 	return CAIRO_TEST_FAILURE;
     }
 
@@ -296,12 +278,17 @@ main (void)
     cairo_destroy (cr);
     if (status != CAIRO_STATUS_SUCCESS) {
 	cairo_surface_destroy (surface);
-	cairo_test_fini (&ctx);
 	return CAIRO_TEST_FAILURE;
     }
 
     cairo_surface_destroy (surface);
-    cairo_test_fini (&ctx);
 
-    return cairo_test (&test);
+    return CAIRO_TEST_SUCCESS;
 }
+
+CAIRO_TEST (copy_path,
+	    "Tests calls to path_data functions: cairo_copy_path, cairo_copy_path_flat, and cairo_append_path",
+	    "path", /* keywords */
+	    NULL, /* requirements */
+	    45, 53,
+	    preamble, draw)
diff --git a/test/create-for-stream.c b/test/create-for-stream.c
index f085496..f39e9cf 100644
--- a/test/create-for-stream.c
+++ b/test/create-for-stream.c
@@ -23,12 +23,12 @@
  * Author: Kristian Høgsberg <krh at redhat.com>
  */
 
+#include "cairo-test.h"
+
 #include <stdio.h>
 #include <string.h>
 #include <errno.h>
 
-#include <cairo.h>
-
 #if CAIRO_HAS_PS_SURFACE
 #include <cairo-ps.h>
 #endif
@@ -46,7 +46,7 @@
 /* The main test suite doesn't test the *_create_for_stream
  * constructors for the PDF, PS and SVG surface, so we do that here.
  * We draw to an in-memory buffer using the stream constructor and
- * compare the output to the contents of a file writting using the
+ * compare the output to the contents of a file written using the
  * file constructor.
  */
 
@@ -57,6 +57,8 @@
 #define WIDTH_IN_POINTS  (WIDTH_IN_INCHES  * 72.0)
 #define HEIGHT_IN_POINTS (HEIGHT_IN_INCHES * 72.0)
 
+#define BASENAME "create-for-stream-out"
+
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -232,28 +234,24 @@ test_surface (const cairo_test_context_t *ctx,
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
+static cairo_test_status_t
+preamble (cairo_test_context_t *ctx)
 {
-    cairo_test_context_t ctx;
     cairo_test_status_t status = CAIRO_TEST_UNTESTED;
     cairo_test_status_t test_status;
-    const char test_name[] = "create-for-stream";
-
-    cairo_test_init (&ctx, test_name);
 
 #if CAIRO_HAS_PS_SURFACE
-    if (cairo_test_is_target_enabled (&ctx, "ps2") ||
-	cairo_test_is_target_enabled (&ctx, "ps3"))
+    if (cairo_test_is_target_enabled (ctx, "ps2") ||
+	cairo_test_is_target_enabled (ctx, "ps3"))
     {
 	if (status == CAIRO_TEST_UNTESTED)
 	    status = CAIRO_TEST_SUCCESS;
 
-	test_status = test_surface (&ctx, "ps", "create-for-stream.ps",
+	test_status = test_surface (ctx, "ps", BASENAME ".ps",
 				    cairo_ps_surface_create,
 				    cairo_ps_surface_create_for_stream);
-	cairo_test_log (&ctx, "TEST: %s TARGET: %s RESULT: %s\n",
-			test_name, "ps",
+	cairo_test_log (ctx, "TEST: %s TARGET: %s RESULT: %s\n",
+			ctx->test->name, "ps",
 			test_status ? "FAIL" : "PASS");
 	if (status == CAIRO_TEST_SUCCESS)
 	    status = test_status;
@@ -261,15 +259,15 @@ main (void)
 #endif
 
 #if CAIRO_HAS_PDF_SURFACE
-    if (cairo_test_is_target_enabled (&ctx, "pdf")) {
+    if (cairo_test_is_target_enabled (ctx, "pdf")) {
 	if (status == CAIRO_TEST_UNTESTED)
 	    status = CAIRO_TEST_SUCCESS;
 
-	test_status = test_surface (&ctx, "pdf", "create-for-stream.pdf",
+	test_status = test_surface (ctx, "pdf", BASENAME ".pdf",
 				    cairo_pdf_surface_create,
 				    cairo_pdf_surface_create_for_stream);
-	cairo_test_log (&ctx, "TEST: %s TARGET: %s RESULT: %s\n",
-			test_name, "pdf",
+	cairo_test_log (ctx, "TEST: %s TARGET: %s RESULT: %s\n",
+			ctx->test->name, "pdf",
 			test_status ? "FAIL" : "PASS");
 	if (status == CAIRO_TEST_SUCCESS)
 	    status = test_status;
@@ -277,24 +275,29 @@ main (void)
 #endif
 
 #if CAIRO_HAS_SVG_SURFACE
-    if (cairo_test_is_target_enabled (&ctx, "svg11") ||
-	cairo_test_is_target_enabled (&ctx, "svg12"))
+    if (cairo_test_is_target_enabled (ctx, "svg11") ||
+	cairo_test_is_target_enabled (ctx, "svg12"))
     {
 	if (status == CAIRO_TEST_UNTESTED)
 	    status = CAIRO_TEST_SUCCESS;
 
-	test_status = test_surface (&ctx, "svg", "create-for-stream.svg",
+	test_status = test_surface (ctx, "svg", BASENAME ".svg",
 				    cairo_svg_surface_create,
 				    cairo_svg_surface_create_for_stream);
-	cairo_test_log (&ctx, "TEST: %s TARGET: %s RESULT: %s\n",
-			test_name, "svg",
+	cairo_test_log (ctx, "TEST: %s TARGET: %s RESULT: %s\n",
+			ctx->test->name, "svg",
 			test_status ? "FAIL" : "PASS");
 	if (status == CAIRO_TEST_SUCCESS)
 	    status = test_status;
     }
 #endif
 
-    cairo_test_fini (&ctx);
-
     return status;
 }
+
+CAIRO_TEST (create_for_stream,
+	    "Checks creating vector surfaces with user defined I/O\n",
+	    "stream", /* keywords */
+	    "target=vector", /* requirements */
+	    0, 0,
+	    preamble, NULL)
diff --git a/test/create-from-png-stream.c b/test/create-from-png-stream.c
index 6dedeb8..e03ccc7 100644
--- a/test/create-from-png-stream.c
+++ b/test/create-from-png-stream.c
@@ -31,15 +31,6 @@
 #define WIDTH 2
 #define HEIGHT 2
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "create-from-png-stream",
-    "Tests the creation of an image surface from a PNG using a FILE *",
-    WIDTH, HEIGHT,
-    draw
-};
-
 static cairo_status_t
 read_png_from_file (void *closure, unsigned char *data, unsigned int length)
 {
@@ -96,8 +87,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (create_from_png_stream,
+	    "Tests the creation of an image surface from a PNG using a FILE *",
+	    "png", /* keywords */
+	    NULL, /* requirements */
+	    WIDTH, HEIGHT,
+	    NULL, draw)
diff --git a/test/create-from-png.c b/test/create-from-png.c
index 9e2ad7f..647ef13 100644
--- a/test/create-from-png.c
+++ b/test/create-from-png.c
@@ -30,15 +30,6 @@
 #define WIDTH 2
 #define HEIGHT 2
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "create-from-png",
-    "Tests the creation of an image surface from a PNG file",
-    WIDTH, HEIGHT,
-    draw
-};
-
 static cairo_status_t
 no_memory_error (void *closure, unsigned char *data, unsigned int size)
 {
@@ -80,20 +71,17 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
+static cairo_test_status_t
+preamble (cairo_test_context_t *ctx)
 {
-    cairo_test_context_t ctx;
     char *filename;
     cairo_surface_t *surface;
     cairo_status_t status;
     cairo_test_status_t result = CAIRO_TEST_SUCCESS;
 
-    cairo_test_init (&ctx, "create-from-png");
-
     surface = cairo_image_surface_create_from_png ("___THIS_FILE_DOES_NOT_EXIST___");
     if (cairo_surface_status (surface) != CAIRO_STATUS_FILE_NOT_FOUND) {
-	cairo_test_log (&ctx, "Error: expected \"file not found\", but got: %s\n",
+	cairo_test_log (ctx, "Error: expected \"file not found\", but got: %s\n",
 			cairo_status_to_string (cairo_surface_status (surface)));
 	result = CAIRO_TEST_FAILURE;
     }
@@ -101,7 +89,7 @@ main (void)
 
     surface = cairo_image_surface_create_from_png_stream (no_memory_error, NULL);
     if (cairo_surface_status (surface) != CAIRO_STATUS_NO_MEMORY) {
-	cairo_test_log (&ctx, "Error: expected \"out of memory\", but got: %s\n",
+	cairo_test_log (ctx, "Error: expected \"out of memory\", but got: %s\n",
 			cairo_status_to_string (cairo_surface_status (surface)));
 	result = CAIRO_TEST_FAILURE;
     }
@@ -109,19 +97,19 @@ main (void)
 
     surface = cairo_image_surface_create_from_png_stream (read_error, NULL);
     if (cairo_surface_status (surface) != CAIRO_STATUS_READ_ERROR) {
-	cairo_test_log (&ctx, "Error: expected \"read error\", but got: %s\n",
+	cairo_test_log (ctx, "Error: expected \"read error\", but got: %s\n",
 			cairo_status_to_string (cairo_surface_status (surface)));
 	result = CAIRO_TEST_FAILURE;
     }
     cairo_surface_destroy (surface);
 
     /* cheekily test error propagation from the user write funcs as well ... */
-    xasprintf (&filename, "%s/%s", ctx.srcdir,
+    xasprintf (&filename, "%s/%s", ctx->srcdir,
 	       "create-from-png-ref.png");
 
     surface = cairo_image_surface_create_from_png (filename);
     if (cairo_surface_status (surface)) {
-	cairo_test_log (&ctx, "Error reading PNG image %s: %s\n",
+	cairo_test_log (ctx, "Error reading PNG image %s: %s\n",
 			filename,
 			cairo_status_to_string (cairo_surface_status (surface)));
 	result = CAIRO_TEST_FAILURE;
@@ -130,7 +118,7 @@ main (void)
 					       (cairo_write_func_t) no_memory_error,
 					       NULL);
 	if (status != CAIRO_STATUS_NO_MEMORY) {
-	    cairo_test_log (&ctx, "Error: expected \"out of memory\", but got: %s\n",
+	    cairo_test_log (ctx, "Error: expected \"out of memory\", but got: %s\n",
 			    cairo_status_to_string (status));
 	    result = CAIRO_TEST_FAILURE;
 	}
@@ -139,14 +127,14 @@ main (void)
 						    (cairo_write_func_t) read_error,
 						    NULL);
 	if (status != CAIRO_STATUS_READ_ERROR) {
-	    cairo_test_log (&ctx, "Error: expected \"read error\", but got: %s\n",
+	    cairo_test_log (ctx, "Error: expected \"read error\", but got: %s\n",
 			    cairo_status_to_string (status));
 	    result = CAIRO_TEST_FAILURE;
 	}
 
 	/* and check that error has not propagated to the surface */
 	if (cairo_surface_status (surface)) {
-	    cairo_test_log (&ctx, "Error: user write error propagated to surface: %s",
+	    cairo_test_log (ctx, "Error: user write error propagated to surface: %s",
 			    cairo_status_to_string (cairo_surface_status (surface)));
 	    result = CAIRO_TEST_FAILURE;
 	}
@@ -155,32 +143,32 @@ main (void)
     free (filename);
 
     /* check that loading alpha/opaque PNGs generate the correct surfaces */
-    xasprintf (&filename, "%s/%s", ctx.srcdir,
+    xasprintf (&filename, "%s/%s", ctx->srcdir,
 	       "create-from-png-alpha-ref.png");
     surface = cairo_image_surface_create_from_png (filename);
     if (cairo_surface_status (surface)) {
-	cairo_test_log (&ctx, "Error reading PNG image %s: %s\n",
+	cairo_test_log (ctx, "Error reading PNG image %s: %s\n",
 			filename,
 			cairo_status_to_string (cairo_surface_status (surface)));
 	result = CAIRO_TEST_FAILURE;
     } else if (cairo_image_surface_get_format (surface) != CAIRO_FORMAT_ARGB32) {
-	cairo_test_log (&ctx, "Error reading PNG image %s: did not create an ARGB32 image\n",
+	cairo_test_log (ctx, "Error reading PNG image %s: did not create an ARGB32 image\n",
 			filename);
 	result = CAIRO_TEST_FAILURE;
     }
     free (filename);
     cairo_surface_destroy (surface);
 
-    xasprintf (&filename, "%s/%s", ctx.srcdir,
+    xasprintf (&filename, "%s/%s", ctx->srcdir,
 	       "create-from-png-ref.png");
     surface = cairo_image_surface_create_from_png (filename);
     if (cairo_surface_status (surface)) {
-	cairo_test_log (&ctx, "Error reading PNG image %s: %s\n",
+	cairo_test_log (ctx, "Error reading PNG image %s: %s\n",
 			filename,
 			cairo_status_to_string (cairo_surface_status (surface)));
 	result = CAIRO_TEST_FAILURE;
     } else if (cairo_image_surface_get_format (surface) != CAIRO_FORMAT_RGB24) {
-	cairo_test_log (&ctx, "Error reading PNG image %s: did not create an RGB24 image\n",
+	cairo_test_log (ctx, "Error reading PNG image %s: did not create an RGB24 image\n",
 			filename);
 	result = CAIRO_TEST_FAILURE;
     }
@@ -188,32 +176,32 @@ main (void)
     cairo_surface_destroy (surface);
 
     /* check paletted PNGs */
-    xasprintf (&filename, "%s/%s", ctx.srcdir,
+    xasprintf (&filename, "%s/%s", ctx->srcdir,
 	       "create-from-png-indexed-alpha-ref.png");
     surface = cairo_image_surface_create_from_png (filename);
     if (cairo_surface_status (surface)) {
-	cairo_test_log (&ctx, "Error reading PNG image %s: %s\n",
+	cairo_test_log (ctx, "Error reading PNG image %s: %s\n",
 			filename,
 			cairo_status_to_string (cairo_surface_status (surface)));
 	result = CAIRO_TEST_FAILURE;
     } else if (cairo_image_surface_get_format (surface) != CAIRO_FORMAT_ARGB32) {
-	cairo_test_log (&ctx, "Error reading PNG image %s: did not create an ARGB32 image\n",
+	cairo_test_log (ctx, "Error reading PNG image %s: did not create an ARGB32 image\n",
 			filename);
 	result = CAIRO_TEST_FAILURE;
     }
     free (filename);
     cairo_surface_destroy (surface);
 
-    xasprintf (&filename, "%s/%s", ctx.srcdir,
+    xasprintf (&filename, "%s/%s", ctx->srcdir,
 	       "create-from-png-indexed-ref.png");
     surface = cairo_image_surface_create_from_png (filename);
     if (cairo_surface_status (surface)) {
-	cairo_test_log (&ctx, "Error reading PNG image %s: %s\n",
+	cairo_test_log (ctx, "Error reading PNG image %s: %s\n",
 			filename,
 			cairo_status_to_string (cairo_surface_status (surface)));
 	result = CAIRO_TEST_FAILURE;
     } else if (cairo_image_surface_get_format (surface) != CAIRO_FORMAT_RGB24) {
-	cairo_test_log (&ctx, "Error reading PNG image %s: did not create an RGB24 image\n",
+	cairo_test_log (ctx, "Error reading PNG image %s: did not create an RGB24 image\n",
 			filename);
 	result = CAIRO_TEST_FAILURE;
     }
@@ -221,42 +209,44 @@ main (void)
     cairo_surface_destroy (surface);
 
     /* check grayscale PNGs */
-    xasprintf (&filename, "%s/%s", ctx.srcdir,
+    xasprintf (&filename, "%s/%s", ctx->srcdir,
 	       "create-from-png-gray-alpha-ref.png");
     surface = cairo_image_surface_create_from_png (filename);
     if (cairo_surface_status (surface)) {
-	cairo_test_log (&ctx, "Error reading PNG image %s: %s\n",
+	cairo_test_log (ctx, "Error reading PNG image %s: %s\n",
 			filename,
 			cairo_status_to_string (cairo_surface_status (surface)));
 	result = CAIRO_TEST_FAILURE;
     } else if (cairo_image_surface_get_format (surface) != CAIRO_FORMAT_ARGB32) {
-	cairo_test_log (&ctx, "Error reading PNG image %s: did not create an ARGB32 image\n",
+	cairo_test_log (ctx, "Error reading PNG image %s: did not create an ARGB32 image\n",
 			filename);
 	result = CAIRO_TEST_FAILURE;
     }
     free (filename);
     cairo_surface_destroy (surface);
 
-    xasprintf (&filename, "%s/%s", ctx.srcdir,
+    xasprintf (&filename, "%s/%s", ctx->srcdir,
 	       "create-from-png-gray-ref.png");
     surface = cairo_image_surface_create_from_png (filename);
     if (cairo_surface_status (surface)) {
-	cairo_test_log (&ctx, "Error reading PNG image %s: %s\n",
+	cairo_test_log (ctx, "Error reading PNG image %s: %s\n",
 			filename,
 			cairo_status_to_string (cairo_surface_status (surface)));
 	result = CAIRO_TEST_FAILURE;
     } else if (cairo_image_surface_get_format (surface) != CAIRO_FORMAT_RGB24) {
-	cairo_test_log (&ctx, "Error reading PNG image %s: did not create an RGB24 image\n",
+	cairo_test_log (ctx, "Error reading PNG image %s: did not create an RGB24 image\n",
 			filename);
 	result = CAIRO_TEST_FAILURE;
     }
     free (filename);
     cairo_surface_destroy (surface);
 
-    cairo_test_fini (&ctx);
-
-    if (result != CAIRO_TEST_SUCCESS)
-	return result;
-
-    return cairo_test (&test);
+    return result;
 }
+
+CAIRO_TEST (create_from_png,
+	    "Tests the creation of an image surface from a PNG file",
+	    "png", /* keywords */
+	    NULL, /* requirements */
+	    WIDTH, HEIGHT,
+	    preamble, draw)
diff --git a/test/dash-caps-joins.c b/test/dash-caps-joins.c
index 680a7fb..4347c6d 100644
--- a/test/dash-caps-joins.c
+++ b/test/dash-caps-joins.c
@@ -31,20 +31,10 @@
 
 #include "cairo-test.h"
 
-#define LINE_WIDTH 	10.
-#define SIZE 		(5 * LINE_WIDTH)
+#define LINE_WIDTH	10.
+#define SIZE		(5 * LINE_WIDTH)
 #define PAD		(2 * LINE_WIDTH)
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "dash-caps-joins",
-    "Test caps and joins when dashing",
-    3 * (PAD + SIZE) + PAD,
-    PAD + SIZE + PAD + SIZE + PAD,
-    draw
-};
-
 static void
 make_path (cairo_t *cr)
 {
@@ -105,8 +95,10 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (dash_caps_joins,
+	    "Test caps and joins when dashing",
+	    "dash, stroke", /* keywords */
+	    NULL, /* requirements */
+	    3 * (PAD + SIZE) + PAD,
+	    PAD + SIZE + PAD + SIZE + PAD,
+	    NULL, draw)
diff --git a/test/dash-curve.c b/test/dash-curve.c
index b98f4f1..c319980 100644
--- a/test/dash-curve.c
+++ b/test/dash-curve.c
@@ -25,15 +25,6 @@
 
 #include "cairo-test.h"
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "dash-curve",
-    "Tries to explore the state space of the dashing code along curves",
-    25*60, 4*60,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -67,8 +58,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (dash_curve,
+	    "Tries to explore the state space of the dashing code along curves",
+	    "dash, stroke", /* keywords */
+	    NULL, /* requirements */
+	    25*60, 4*60,
+	    NULL, draw)
diff --git a/test/dash-no-dash.c b/test/dash-no-dash.c
index e9e9c5d..e03094a 100644
--- a/test/dash-no-dash.c
+++ b/test/dash-no-dash.c
@@ -31,15 +31,6 @@
 #define HEIGHT		(PAD + 4 * (LINE_WIDTH + PAD))
 #define WIDTH		16
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "dash-no-dash",
-    "Tests that we can actually turn dashing on and off again",
-    WIDTH, HEIGHT,
-    draw
-};
-
 static void
 line (cairo_t *cr)
 {
@@ -88,8 +79,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (dash_no_dash,
+	    "Tests that we can actually turn dashing on and off again",
+	    "dash, stroke", /* keywords */
+	    NULL, /* requirements */
+	    WIDTH, HEIGHT,
+	    NULL, draw)
diff --git a/test/dash-offset-negative.c b/test/dash-offset-negative.c
index adfe265..8766cc5 100644
--- a/test/dash-offset-negative.c
+++ b/test/dash-offset-negative.c
@@ -34,15 +34,6 @@
  *	https://bugs.freedesktop.org/show_bug.cgi?id=2729
  */
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "dash-offset-negative",
-    "Tests cairo_set_dash with a negative offset",
-    IMAGE_WIDTH, IMAGE_HEIGHT,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -101,8 +92,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (dash_offset_negative,
+	    "Tests cairo_set_dash with a negative offset",
+	    "dash, stroke", /* keywords */
+	    NULL, /* requirements */
+	    IMAGE_WIDTH, IMAGE_HEIGHT,
+	    NULL, draw)
diff --git a/test/dash-scale.c b/test/dash-scale.c
index b00b0f1..afe3f9e 100644
--- a/test/dash-scale.c
+++ b/test/dash-scale.c
@@ -25,20 +25,10 @@
 
 #include "cairo-test.h"
 
-#define LINE_WIDTH 	8.
-#define SIZE 		(5 * LINE_WIDTH)
+#define LINE_WIDTH	8.
+#define SIZE		(5 * LINE_WIDTH)
 #define PAD		(2 * LINE_WIDTH)
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "dash-scale",
-    "Test interactions of cairo_set_dash and cairo_scale, (in particular with a non-uniformly scaled pen)",
-    3 * (PAD + SIZE) + PAD,
-    PAD + 5 * SIZE + 2 * (2 * PAD) + PAD,
-    draw
-};
-
 static void
 make_path (cairo_t *cr)
 {
@@ -121,8 +111,10 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (dash_scale,
+	    "Test interactions of cairo_set_dash and cairo_scale, (in particular with a non-uniformly scaled pen)",
+	    "dash, stroke, transform", /* keywords */
+	    NULL, /* requirements */
+	    3 * (PAD + SIZE) + PAD,
+	    PAD + 5 * SIZE + 2 * (2 * PAD) + PAD,
+	    NULL, draw)
diff --git a/test/dash-state.c b/test/dash-state.c
index f74e598..5276aea 100644
--- a/test/dash-state.c
+++ b/test/dash-state.c
@@ -25,21 +25,12 @@
 
 #include "cairo-test.h"
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "dash-state",
-    "Tries to explore the state space of the dashing code",
-    25*60, 4*60,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
     double dashes[2] = {20, 20};
     int a=0, b=0, c=0;
-    
+
     cairo_set_source_rgb (cr, 0, 0, 0);
     cairo_paint (cr);
 
@@ -65,8 +56,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (dash_state,
+	    "Tries to explore the state space of the dashing code",
+	    "dash, stroke", /* keywords */
+	    NULL, /* requirements */
+	    25*60, 4*60,
+	    NULL, draw)
diff --git a/test/dash-zero-length.c b/test/dash-zero-length.c
index e6f2da6..5ab944b 100644
--- a/test/dash-zero-length.c
+++ b/test/dash-zero-length.c
@@ -33,15 +33,6 @@
  * on invisible lines.
  */
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "dash-zero-length",
-    "Tests cairo_set_dash with zero length",
-    IMAGE_WIDTH, IMAGE_HEIGHT,
-    draw
-};
-
 static void
 draw_dash (cairo_t *cr, double *dash, int num_dashes)
 {
@@ -111,8 +102,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (dash_zero_length,
+	    "Tests cairo_set_dash with zero length",
+	    "dash, stroke", /* keywords */
+	    NULL, /* requirements */
+	    IMAGE_WIDTH, IMAGE_HEIGHT,
+	    NULL, draw)
diff --git a/test/degenerate-arc.c b/test/degenerate-arc.c
index d030598..ab65774 100644
--- a/test/degenerate-arc.c
+++ b/test/degenerate-arc.c
@@ -30,15 +30,6 @@
 
 #include "cairo-test.h"
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "degenerate-arc",
-    "Tests the behaviour of degenerate arcs",
-    40, 40,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -75,8 +66,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (degenerate_arc,
+	    "Tests the behaviour of degenerate arcs",
+	    "degenerate", /* keywords */
+	    NULL, /* requirements */
+	    40, 40,
+	    NULL, draw)
diff --git a/test/degenerate-dash.c b/test/degenerate-dash.c
index 4efbef6..4bc0a42 100644
--- a/test/degenerate-dash.c
+++ b/test/degenerate-dash.c
@@ -33,15 +33,6 @@
 
 #define PAD 5
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "degenerate-dash",
-    "Tests the behaviour of dashed segments that end on a off-on transition",
-    210 + 2*PAD, 210 + 2*PAD,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -90,8 +81,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (degenerate_dash,
+	    "Tests the behaviour of dashed segments that end on a off-on transition",
+	    "XFAIL=ps dash, degenerate", /* keywords */
+	    NULL, /* requirementts */
+	    210 + 2*PAD, 210 + 2*PAD,
+	    NULL, draw)
diff --git a/test/degenerate-path.c b/test/degenerate-path.c
index edaeed0..b4c30ee 100644
--- a/test/degenerate-path.c
+++ b/test/degenerate-path.c
@@ -30,16 +30,6 @@
 
 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0]))
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "degenerate-path",
-    "Tests the behaviour of degenerate paths with different cap types"
-    "\nPS backend currently fails for unknown reason (cairo? GS?).",
-    3*(PAD+LINE_WIDTH+PAD), 8*(LINE_WIDTH+PAD) + PAD,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -120,8 +110,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (degenerate_path,
+	    "Tests the behaviour of degenerate paths with different cap types",
+	    "XFAIL=ps degenerate", /* keywords */
+	    NULL, /* requirements */
+	    3*(PAD+LINE_WIDTH+PAD), 8*(LINE_WIDTH+PAD) + PAD,
+	    NULL, draw)
diff --git a/test/degenerate-pen.c b/test/degenerate-pen.c
index deb7b2a..ec8bd19 100644
--- a/test/degenerate-pen.c
+++ b/test/degenerate-pen.c
@@ -26,8 +26,6 @@
 
 #include "cairo-test.h"
 
-static cairo_test_draw_function_t draw;
-
 #define SIZE   20
 #define PAD    5
 #define WIDTH  (PAD + 3 * (PAD + SIZE) + PAD)
@@ -50,13 +48,6 @@ static cairo_test_draw_function_t draw;
  * pen doing slope comparisons.
  */
 
-static const cairo_test_t test = {
-    "degenerate-pen",
-    "Test round joins with a pen that's transformed to a line",
-    WIDTH, HEIGHT,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -106,8 +97,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (degenerate_pen,
+	    "Test round joins with a pen that's transformed to a line",
+	    "degenerate", /* keywords */
+	    NULL, /* requirements */
+	    WIDTH, HEIGHT,
+	    NULL, draw)
diff --git a/test/device-offset-fractional.c b/test/device-offset-fractional.c
index d301541..adc2116 100644
--- a/test/device-offset-fractional.c
+++ b/test/device-offset-fractional.c
@@ -31,15 +31,6 @@
 #define PAD 4
 #define COUNT 4
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "device-offset-fractional",
-    "Test using image surfaces with fractional device-offsets as sources.",
-    COUNT*(SIZE+PAD+.5)+PAD, COUNT*(SIZE+PAD+.5)+PAD,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -73,8 +64,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (device_offset_fractional,
+	    "Test using image surfaces with fractional device-offsets as sources.",
+	    "device-offset", /* keywords */
+	    NULL, /* requirements */
+	    COUNT*(SIZE+PAD+.5)+PAD, COUNT*(SIZE+PAD+.5)+PAD,
+	    NULL, draw)
diff --git a/test/device-offset-positive.c b/test/device-offset-positive.c
index 082f3d7..4ea9469 100644
--- a/test/device-offset-positive.c
+++ b/test/device-offset-positive.c
@@ -29,15 +29,6 @@
 #define SIZE 10
 #define PAD 2
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "device-offset-positive",
-    "Simple test using a surface with a positive device-offset as a source.",
-    SIZE, SIZE,
-    draw
-};
-
 static void
 draw_square (cairo_t *cr)
 {
@@ -82,8 +73,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (device_offset_positive,
+	    "Simple test using a surface with a positive device-offset as a source.",
+	    "device-offset", /* keywords */
+	    NULL, /* requirements */
+	    SIZE, SIZE,
+	    NULL, draw)
diff --git a/test/device-offset-scale.c b/test/device-offset-scale.c
index 7effebe..11e68f9 100644
--- a/test/device-offset-scale.c
+++ b/test/device-offset-scale.c
@@ -28,16 +28,6 @@
 #define WIDTH 20
 #define HEIGHT 20
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "device-offset-scale",
-    "Test that the device-offset transform is transformed by the ctm."
-    "\nCurrently fails with the SVG backend.",
-    WIDTH, HEIGHT,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -75,8 +65,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (device_offset_scale,
+	    "Test that the device-offset transform is transformed by the ctm.",
+	    "XFAIL=svg device-offset", /* keywords */
+	    NULL, /* requirements */
+	    WIDTH, HEIGHT,
+	    NULL, draw)
diff --git a/test/device-offset.c b/test/device-offset.c
index a7a6731..1bf5283 100644
--- a/test/device-offset.c
+++ b/test/device-offset.c
@@ -29,15 +29,6 @@
 #define SIZE 10
 #define PAD 2
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "device-offset",
-    "Simple test using a surface with a negative device-offset as a source.",
-    SIZE, SIZE,
-    draw
-};
-
 static void
 draw_square (cairo_t *cr)
 {
@@ -83,8 +74,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (device_offset,
+	    "Simple test using a surface with a negative device-offset as a source.",
+	    "device-offset", /* keywords */
+	    NULL, /* requirements */
+	    SIZE, SIZE,
+	    NULL, draw)
diff --git a/test/extend-pad.c b/test/extend-pad.c
index b122f15..ed4ffd0 100644
--- a/test/extend-pad.c
+++ b/test/extend-pad.c
@@ -30,15 +30,6 @@
 
 #define SIZE 90
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "extend-pad",
-    "Test CAIRO_EXTEND_PAD for surface patterns",
-    SIZE, SIZE,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -94,8 +85,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (extend_pad,
+	    "Test CAIRO_EXTEND_PAD for surface patterns",
+	    "XFAIL=!image,pdf,ps,svg extend", /* keywords */
+	    NULL, /* requirements */
+	    SIZE, SIZE,
+	    NULL, draw)
diff --git a/test/extend-reflect-similar.c b/test/extend-reflect-similar.c
index c1914b3..fa376a7 100644
--- a/test/extend-reflect-similar.c
+++ b/test/extend-reflect-similar.c
@@ -1,15 +1,6 @@
 #include "cairo-test.h"
 
-const char	png_filename[]	= "romedalen.png";
-
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "extend-reflect-similar",
-    "Test CAIRO_EXTEND_REFLECT for surface patterns",
-    256 + 32*2, 192 + 32*2,
-    draw
-};
+static const char *png_filename = "romedalen.png";
 
 static cairo_surface_t *
 clone_similar_surface (cairo_surface_t * target, cairo_surface_t *surface)
@@ -52,8 +43,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (extend_reflect_similar,
+	    "Test CAIRO_EXTEND_REFLECT for surface patterns",
+	    "extend", /* keywords */
+	    NULL, /* requirements */
+	    256 + 32*2, 192 + 32*2,
+	    NULL, draw)
diff --git a/test/extend-reflect.c b/test/extend-reflect.c
index 6175657..16b08c1 100644
--- a/test/extend-reflect.c
+++ b/test/extend-reflect.c
@@ -2,16 +2,7 @@
 #include "cairo-test.h"
 #include <stdio.h>
 
-const char	png_filename[]	= "romedalen.png";
-
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "extend-reflect",
-    "Test CAIRO_EXTEND_REFLECT for surface patterns",
-    256 + 32*2, 192 + 32*2,
-    draw
-};
+static const char *png_filename = "romedalen.png";
 
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
@@ -30,8 +21,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (extend_reflect,
+	    "Test CAIRO_EXTEND_REFLECT for surface patterns",
+	    "extend", /* keywords */
+	    NULL, /* requirements */
+	    256 + 32*2, 192 + 32*2,
+	    NULL, draw)
diff --git a/test/extend-repeat-similar.c b/test/extend-repeat-similar.c
index 88d4a2b..08cfd29 100644
--- a/test/extend-repeat-similar.c
+++ b/test/extend-repeat-similar.c
@@ -1,15 +1,6 @@
 #include "cairo-test.h"
 
-const char	png_filename[]	= "romedalen.png";
-
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "extend-repeat-similar",
-    "Test CAIRO_EXTEND_REPEAT for surface patterns",
-    256 + 32*2, 192 + 32*2,
-    draw
-};
+static const char *png_filename = "romedalen.png";
 
 static cairo_surface_t *
 clone_similar_surface (cairo_surface_t * target, cairo_surface_t *surface)
@@ -52,8 +43,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (extend_repeat_similar,
+	    "Test CAIRO_EXTEND_REPEAT for surface patterns",
+	    "extend", /* keywords */
+	    NULL, /* requirements */
+	    256 + 32*2, 192 + 32*2,
+	    NULL, draw)
diff --git a/test/extend-repeat.c b/test/extend-repeat.c
index 32c43a5..e6c0bcc 100644
--- a/test/extend-repeat.c
+++ b/test/extend-repeat.c
@@ -1,15 +1,6 @@
 #include "cairo-test.h"
 
-const char	png_filename[]	= "romedalen.png";
-
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "extend-repeat",
-    "Test CAIRO_EXTEND_REPEAT for surface patterns",
-    256 + 32*2, 192 + 32*2,
-    draw
-};
+static const char *png_filename = "romedalen.png";
 
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
@@ -28,8 +19,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (extend_repeat,
+	    "Test CAIRO_EXTEND_REPEAT for surface patterns",
+	    "extend", /* keywords */
+	    NULL, /* requirements */
+	    256 + 32*2, 192 + 32*2,
+	    NULL, draw)
diff --git a/test/fallback-resolution.c b/test/fallback-resolution.c
index 8b5842e..ab6a0ed 100644
--- a/test/fallback-resolution.c
+++ b/test/fallback-resolution.c
@@ -295,10 +295,9 @@ generate_reference (double ppi_x, double ppi_y, const char *filename)
 }
 #endif
 
-int
-main (void)
+static cairo_test_status_t
+preamble (cairo_test_context_t *ctx)
 {
-    cairo_test_context_t ctx;
     cairo_t *cr;
     cairo_test_status_t ret = CAIRO_TEST_UNTESTED;
     double ppi[] = { 600., 300., 150., 75., 72, 37.5 };
@@ -307,8 +306,6 @@ main (void)
 
     num_ppi = sizeof (ppi) / sizeof (ppi[0]);
 
-    cairo_test_init (&ctx, "fallback-resolution");
-
 #if GENERATE_REFERENCE
     for (ppi_x = 0; ppi_x < num_ppi; ppi_x++) {
 	for (ppi_y = 0; ppi_y < num_ppi; ppi_y++) {
@@ -321,8 +318,8 @@ main (void)
     }
 #endif
 
-    for (i = 0; i < ctx.num_targets; i++) {
-	const cairo_boilerplate_target_t *target = ctx.targets_to_test[i];
+    for (i = 0; i < ctx->num_targets; i++) {
+	const cairo_boilerplate_target_t *target = ctx->targets_to_test[i];
 	cairo_surface_t *surface = NULL;
 	char *base_name;
 	void *closure;
@@ -381,7 +378,7 @@ main (void)
 						    0,
 						    &closure);
 		if (surface == NULL || cairo_surface_status (surface)) {
-		    cairo_test_log (&ctx, "Failed to generate surface: %s-%s\n",
+		    cairo_test_log (ctx, "Failed to generate surface: %s-%s\n",
 				    target->name,
 				    format);
 		    free (base_name);
@@ -389,7 +386,7 @@ main (void)
 		    continue;
 		}
 
-		cairo_test_log (&ctx,
+		cairo_test_log (ctx,
 				"Testing fallback-resolution %gx%g with %s target\n",
 				ppi[ppi_x], ppi[ppi_y], target->name);
 		printf ("%s:\t", base_name);
@@ -438,12 +435,12 @@ main (void)
 
 		pass = FALSE;
 		if (status) {
-		    cairo_test_log (&ctx, "Error: Failed to create target surface: %s\n",
+		    cairo_test_log (ctx, "Error: Failed to create target surface: %s\n",
 				    cairo_status_to_string (status));
 		    ret = CAIRO_TEST_FAILURE;
 		} else {
 		    /* extract the image and compare it to our reference */
-		    if (! check_result (&ctx, target, test_name, base_name, surface))
+		    if (! check_result (ctx, target, test_name, base_name, surface))
 			ret = CAIRO_TEST_FAILURE;
 		    else
 			pass = TRUE;
@@ -464,7 +461,12 @@ main (void)
 	}
     }
 
-    cairo_test_fini (&ctx);
-
     return ret;
 }
+
+CAIRO_TEST (fallback_resolution,
+	    "Check handling of fallback resolutions",
+	    "fallback", /* keywords */
+	    NULL, /* requirements */
+	    0, 0,
+	    preamble, NULL)
diff --git a/test/fill-alpha-pattern.c b/test/fill-alpha-pattern.c
index 79722ca..3698779 100644
--- a/test/fill-alpha-pattern.c
+++ b/test/fill-alpha-pattern.c
@@ -28,15 +28,6 @@
 #define SIZE 60 /* needs to be big to check large area effects (dithering) */
 #define PAD 2
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "fill-alpha-pattern",
-    "Tests using set_rgba();fill() over a linear gradient",
-    2*SIZE + 4*PAD, 2*SIZE + 4*PAD,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -88,8 +79,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (fill_alpha_pattern,
+	    "Tests using set_rgba();fill() over a linear gradient",
+	    "fill, alpha", /* keywords */
+	    NULL, /* requirements */
+	    2*SIZE + 4*PAD, 2*SIZE + 4*PAD,
+	    NULL, draw)
diff --git a/test/fill-alpha.c b/test/fill-alpha.c
index db395b3..6c2948d 100644
--- a/test/fill-alpha.c
+++ b/test/fill-alpha.c
@@ -28,15 +28,6 @@
 #define SIZE 60 /* needs to be big to check large area effects (dithering) */
 #define PAD 2
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "fill-alpha",
-    "Tests using set_rgba();fill()",
-    2*SIZE + 4*PAD, 2*SIZE + 4*PAD,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -83,8 +74,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (fill_alpha,
+	    "Tests using set_rgba();fill()",
+	    "fill, alpha", /* keywords */
+	    NULL, /* requirements */
+	    2*SIZE + 4*PAD, 2*SIZE + 4*PAD,
+	    NULL, draw)
diff --git a/test/fill-and-stroke-alpha-add.c b/test/fill-and-stroke-alpha-add.c
index 3575c82..b953b76 100644
--- a/test/fill-and-stroke-alpha-add.c
+++ b/test/fill-and-stroke-alpha-add.c
@@ -29,15 +29,6 @@
 #define PAD 2
 #define SIZE 10
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "fill-and-stroke-alpha-add",
-    "Use a group to fill/stroke a path (each with different alpha) using DEST_OUT and ADD to combine",
-    2 * SIZE + 4 * PAD, SIZE + 2 * PAD,
-    draw
-};
-
 typedef void (*path_func_t) (cairo_t *cr);
 
 static void
@@ -108,8 +99,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (fill_and_stroke_alpha_add,
+	    "Use a group to fill/stroke a path (each with different alpha) using DEST_OUT and ADD to combine",
+	    "XFAIL=svg12 fill-and-stroke, fill, stroke", /* keywords */
+	    NULL, /* requirements */
+	    2 * SIZE + 4 * PAD, SIZE + 2 * PAD,
+	    NULL, draw)
diff --git a/test/fill-and-stroke-alpha.c b/test/fill-and-stroke-alpha.c
index fe02c75..c6d7c00 100644
--- a/test/fill-and-stroke-alpha.c
+++ b/test/fill-and-stroke-alpha.c
@@ -29,15 +29,6 @@
 #define PAD 2
 #define SIZE 10
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "fill-and-stroke-alpha",
-    "Use a group to fill/stroke a path then blend the result with alpha onto the destination",
-    2 * SIZE + 4 * PAD, SIZE + 2 * PAD,
-    draw
-};
-
 typedef void (*path_func_t) (cairo_t *cr);
 
 static void
@@ -102,8 +93,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (fill_and_stroke_alpha,
+	    "Use a group to fill/stroke a path then blend the result with alpha onto the destination",
+	    "fill-and-stroke, fill, stroke", /* keywords */
+	    NULL, /* requirements */
+	    2 * SIZE + 4 * PAD, SIZE + 2 * PAD,
+	    NULL, draw)
diff --git a/test/fill-and-stroke.c b/test/fill-and-stroke.c
index 8bbb261..c983c32 100644
--- a/test/fill-and-stroke.c
+++ b/test/fill-and-stroke.c
@@ -28,15 +28,6 @@
 #define PAD 2
 #define SIZE 10
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "fill-and-stroke",
-    "Tests using cairo_fill_preserve/cairo_stroke to fill/stroke the same path",
-    2 * SIZE + 4 * PAD, SIZE + 2 * PAD,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -59,8 +50,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (fill_and_stroke,
+	    "Tests using cairo_fill_preserve/cairo_stroke to fill/stroke the same path",
+	    "fill-and-stroke, fill, stroke", /* keywords */
+	    NULL, /* requirements */
+	    2 * SIZE + 4 * PAD, SIZE + 2 * PAD,
+	    NULL, draw)
diff --git a/test/fill-degenerate-sort-order.c b/test/fill-degenerate-sort-order.c
index b35f42e..7dc409d 100644
--- a/test/fill-degenerate-sort-order.c
+++ b/test/fill-degenerate-sort-order.c
@@ -36,15 +36,6 @@
 
 #include "cairo-test.h"
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "fill-degenerate-sort-order",
-    "Tests the tessellator's event comparator with degenerate input",
-    190, 120,
-    draw
-};
-
 /* Derived from zrusin's "another" polygon in the performance suite. */
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
@@ -78,8 +69,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (fill_degenerate_sort_order,
+	    "Tests the tessellator's event comparator with degenerate input",
+	    "XFAIL=ps degenerate, fill", /* keywords */
+	    NULL, /* requirements */
+	    190, 120,
+	    NULL, draw)
diff --git a/test/fill-missed-stop.c b/test/fill-missed-stop.c
index cb551c4..5589337 100644
--- a/test/fill-missed-stop.c
+++ b/test/fill-missed-stop.c
@@ -37,16 +37,8 @@
 
 #include "cairo-test.h"
 
-static cairo_test_draw_function_t draw;
 #define SIZE 50
 
-static const cairo_test_t test = {
-    "fill-missed-stop",
-    "Tests that the tessellator doesn't miss stop events when generating trapezoids",
-    SIZE+3, SIZE+3,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -83,8 +75,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (fill_missed_stop,
+	    "Tests that the tessellator doesn't miss stop events when generating trapezoids",
+	    "fill", /* keywords */
+	    NULL, /* requirements */
+	    SIZE+3, SIZE+3,
+	    NULL, draw)
diff --git a/test/fill-rule.c b/test/fill-rule.c
index 8f787ff..66f19b7 100644
--- a/test/fill-rule.c
+++ b/test/fill-rule.c
@@ -66,15 +66,6 @@
 #define LITTLE_STAR_SIZE 20
 #define BIG_STAR_SIZE    80
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "fill-rule",
-    "Tests cairo_set_fill_rule with some star shapes",
-    BIG_STAR_SIZE * 2 + 3, BIG_STAR_SIZE + LITTLE_STAR_SIZE + 3,
-    draw
-};
-
 /* The SVG start trimmed down, but still showing the bug (originally) */
 static void
 little_star_path (cairo_t *cr)
@@ -128,8 +119,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (fill_rule,
+	    "Tests cairo_set_fill_rule with some star shapes",
+	    "fill, path", /* keywords */
+	    NULL, /* requirements */
+	    BIG_STAR_SIZE * 2 + 3, BIG_STAR_SIZE + LITTLE_STAR_SIZE + 3,
+	    NULL, draw)
diff --git a/test/filter-bilinear-extents.c b/test/filter-bilinear-extents.c
index 53789ab..79d36f6 100644
--- a/test/filter-bilinear-extents.c
+++ b/test/filter-bilinear-extents.c
@@ -27,8 +27,6 @@
 
 #include "cairo-test.h"
 
-static cairo_test_draw_function_t draw;
-
 /* This test exercises code that computes the extents of a surface
  * pattern with CAIRO_FILTER_BILINEAR, (where the filtering
  * effectively increases the extents of the pattern).
@@ -40,17 +38,10 @@ static cairo_test_draw_function_t draw;
  */
 
 #define SCALE	10
-#define PAD 	3
+#define PAD	3
 #define WIDTH	(PAD + 3 * SCALE + PAD)
 #define HEIGHT	WIDTH
 
-static const cairo_test_t test = {
-    "filter-bilinear-extents",
-    "Test that pattern extents are properly computed for CAIRO_FILTER_BILINEAR",
-    WIDTH, HEIGHT,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -103,8 +94,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (filter_bilinear_extents,
+	    "Test that pattern extents are properly computed for CAIRO_FILTER_BILINEAR",
+	    "extents", /* keywords */
+	    NULL, /* requirements */
+	    WIDTH, HEIGHT,
+	    NULL, draw)
diff --git a/test/filter-nearest-offset.c b/test/filter-nearest-offset.c
index 76e826e..f22dcf1 100644
--- a/test/filter-nearest-offset.c
+++ b/test/filter-nearest-offset.c
@@ -34,15 +34,6 @@
 #define IMAGE_WIDTH  (PAD + STEPS * (STAMP_WIDTH  + PAD) + PAD)
 #define IMAGE_HEIGHT (PAD + STEPS * (STAMP_HEIGHT + PAD) + PAD)
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "filter-nearest-offset",
-    "Test sampling offset of CAIRO_FILTER_NEAREST",
-    IMAGE_WIDTH, IMAGE_HEIGHT,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -108,8 +99,10 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (filter_nearest_offset,
+	    "Test sampling offset of CAIRO_FILTER_NEAREST"
+	    "\nwrong sampling location for nearest-neighbor filter in libpixman and Render",
+	    "filter", /* keywords */
+	    NULL, /* requirements */
+	    IMAGE_WIDTH, IMAGE_HEIGHT,
+	    NULL, draw)
diff --git a/test/filter-nearest-transformed.c b/test/filter-nearest-transformed.c
index 58acf9a..9629558 100644
--- a/test/filter-nearest-transformed.c
+++ b/test/filter-nearest-transformed.c
@@ -32,14 +32,6 @@
  */
 
 static const char png_filename[] = "romedalen.png";
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "filter-nearest-transformed",
-    "Test sample position when drawing transformed images with FILTER_NEAREST",
-    14, 14,
-    draw
-};
 
 /* A single, black pixel */
 static const uint32_t black_pixel = 0xff000000;
@@ -120,8 +112,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (filter_nearest_transformed,
+	    "Test sample position when drawing transformed images with FILTER_NEAREST",
+	    "filter, nearest", /* keywords */
+	    NULL,
+	    14, 14,
+	    NULL, draw)
diff --git a/test/finer-grained-fallbacks.c b/test/finer-grained-fallbacks.c
index 65bceb4..cd81e96 100644
--- a/test/finer-grained-fallbacks.c
+++ b/test/finer-grained-fallbacks.c
@@ -26,20 +26,11 @@
 
 #include "cairo-test.h"
 
-static cairo_test_draw_function_t draw;
-
 #define CIRCLE_SIZE 10
 #define PAD 2
 #define WIDTH (CIRCLE_SIZE*6.5 + PAD)
 #define HEIGHT (CIRCLE_SIZE*7.0 + PAD)
 
-static const cairo_test_t test = {
-    "finer-grained-fallbacks",
-    "Test that multiple PS/PDF fallback images in various locations are correct",
-    WIDTH, HEIGHT,
-    draw
-};
-
 static void
 draw_circle (cairo_t *cr, double x, double y)
 {
@@ -181,8 +172,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (finer_grained_fallbacks,
+	    "Test that multiple PS/PDF fallback images in various locations are correct",
+	    "XFAIL=svg12 fallbacks", /* keywords */
+	    NULL, /* requirements */
+	    WIDTH, HEIGHT,
+	    NULL, draw)
diff --git a/test/font-face-get-type.c b/test/font-face-get-type.c
index 32ebc47..f6355e3 100644
--- a/test/font-face-get-type.c
+++ b/test/font-face-get-type.c
@@ -25,18 +25,15 @@
 
 #include "cairo-test.h"
 
-int
-main (void)
+static cairo_test_status_t
+preamble (cairo_test_context_t *ctx)
 {
-    cairo_test_context_t ctx;
     cairo_surface_t *surface;
     cairo_t *cr;
     cairo_font_face_t *font_face;
     cairo_scaled_font_t *scaled_font;
 
-    cairo_test_init (&ctx, "font-face-get-type");
-
-    cairo_test_log (&ctx, "Creating cairo context and obtaining a font face\n");
+    cairo_test_log (ctx, "Creating cairo context and obtaining a font face\n");
 
     surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 1, 1);
     cr = cairo_create (surface);
@@ -45,31 +42,34 @@ main (void)
 			    CAIRO_FONT_SLANT_NORMAL,
 			    CAIRO_FONT_WEIGHT_NORMAL);
 
-    cairo_test_log (&ctx, "Testing return value of cairo_font_face_get_type\n");
+    cairo_test_log (ctx, "Testing return value of cairo_font_face_get_type\n");
 
     font_face = cairo_get_font_face (cr);
 
     if (cairo_font_face_get_type (font_face) != CAIRO_FONT_TYPE_TOY) {
-	cairo_test_log (&ctx, "Unexpected value %d from cairo_font_face_get_type (expected %d)\n",
+	cairo_test_log (ctx, "Unexpected value %d from cairo_font_face_get_type (expected %d)\n",
 			cairo_font_face_get_type (font_face), CAIRO_FONT_TYPE_TOY);
-	cairo_test_fini (&ctx);
 	return CAIRO_TEST_FAILURE;
     }
 
-    cairo_test_log (&ctx, "Testing return value of cairo_get_scaled_font\n");
+    cairo_test_log (ctx, "Testing return value of cairo_get_scaled_font\n");
 
     scaled_font = cairo_get_scaled_font (cr);
 
     if (cairo_scaled_font_get_font_face (scaled_font) != font_face) {
-	cairo_test_log (&ctx, "Font face returned from the scaled font is different from that returned by the context\n");
-	cairo_test_fini (&ctx);
+	cairo_test_log (ctx, "Font face returned from the scaled font is different from that returned by the context\n");
 	return CAIRO_TEST_FAILURE;
     }
 
     cairo_destroy (cr);
     cairo_surface_destroy (surface);
 
-    cairo_test_fini (&ctx);
-
     return CAIRO_TEST_SUCCESS;
 }
+
+CAIRO_TEST (font_face_get_type,
+	    "Check the returned type from cairo_select_font_face.",
+	    "font", /* keywords */
+	    NULL, /* requirements */
+	    0, 0,
+	    preamble, NULL)
diff --git a/test/font-matrix-translation.c b/test/font-matrix-translation.c
index 416956f..b83a527 100644
--- a/test/font-matrix-translation.c
+++ b/test/font-matrix-translation.c
@@ -29,15 +29,6 @@
 #define PAD 4
 #define TEXT "text"
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "font-matrix-translation",
-    "Test that translation in a font matrix can be used to offset a string",
-    38, 34,
-    draw
-};
-
 static cairo_bool_t
 text_extents_equal (const cairo_text_extents_t *A,
 	            const cairo_text_extents_t *B)
@@ -142,8 +133,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (font_matrix_translation,
+	    "Test that translation in a font matrix can be used to offset a string",
+	    "font", /* keywords */
+	    NULL, /* requirements */
+	    38, 34,
+	    NULL, draw)
diff --git a/test/font-options.c b/test/font-options.c
index fd61a73..873a5c3 100644
--- a/test/font-options.c
+++ b/test/font-options.c
@@ -25,13 +25,11 @@
 
 #include "cairo-test.h"
 
-#include <cairo.h>
 #include <assert.h>
 
-int
-main (void)
+static cairo_test_status_t
+preamble (cairo_test_context_t *ctx)
 {
-    cairo_test_context_t ctx;
     cairo_font_options_t *default_options;
     cairo_font_options_t *nil_options;
     cairo_surface_t *surface;
@@ -39,8 +37,6 @@ main (void)
     cairo_t *cr;
     cairo_scaled_font_t *scaled_font;
 
-    cairo_test_init (&ctx, "font-options");
-
     /* first check NULL handling of cairo_font_options_t */
     default_options = cairo_font_options_create ();
     assert (cairo_font_options_status (default_options) == CAIRO_STATUS_SUCCESS);
@@ -103,7 +99,12 @@ main (void)
 
     cairo_destroy (cr);
 
-    cairo_test_fini (&ctx);
-
     return CAIRO_TEST_SUCCESS;
 }
+
+CAIRO_TEST (font_options,
+	    "Check setters and getters on cairo_font_options_t.",
+	    "font, api", /* keywords */
+	    NULL, /* requirements */
+	    0, 0,
+	    preamble, NULL)
diff --git a/test/ft-font-create-for-ft-face.c b/test/ft-font-create-for-ft-face.c
index 6b3c511..702b846 100644
--- a/test/ft-font-create-for-ft-face.c
+++ b/test/ft-font-create-for-ft-face.c
@@ -26,15 +26,6 @@
 #include "cairo-test.h"
 #include <cairo-ft.h>
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "ft-font-create-for-ft-face",
-    "Simple test to verify that cairo_ft_font_create_for_ft_face doesn't crash.",
-    0, 0,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -133,8 +124,10 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (ft_font_create_for_ft_face,
+	    "Simple test to verify that cairo_ft_font_create_for_ft_face doesn't crash.",
+	    "ft, font", /* keywords */
+	    NULL, /* requirements */
+	    0, 0,
+	    NULL, draw)
+
diff --git a/test/ft-show-glyphs-positioning.c b/test/ft-show-glyphs-positioning.c
index 33e5055..2d39a0c 100644
--- a/test/ft-show-glyphs-positioning.c
+++ b/test/ft-show-glyphs-positioning.c
@@ -29,15 +29,6 @@
 
 #define TEXT_SIZE 12
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "ft-show-glyphs-positioning",
-    "Test that the PS/PDF glyph positioning optimizations are correct",
-    235, (TEXT_SIZE + 4)*2,
-    draw
-};
-
 typedef struct {
     cairo_glyph_t glyph_list[100];
     int num_glyphs;
@@ -160,8 +151,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (ft_show_glyphs_positioning,
+	    "Test that the PS/PDF glyph positioning optimizations are correct",
+	    "ft, text", /* keywords */
+	    NULL, /* requirements */
+	    235, (TEXT_SIZE + 4)*2,
+	    NULL, draw)
diff --git a/test/ft-show-glyphs-table.c b/test/ft-show-glyphs-table.c
index cc34c6d..e86f149 100644
--- a/test/ft-show-glyphs-table.c
+++ b/test/ft-show-glyphs-table.c
@@ -54,15 +54,6 @@
  * the code well.
  */
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "ft-show-glyphs-table",
-    "Test cairo_show_glyphs with cairo-ft backend and glyphs laid out in a table",
-    WIDTH, HEIGHT,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -109,8 +100,10 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (ft_show_glyphs_table,
+	    "Test cairo_show_glyphs with cairo-ft backend and glyphs laid out in a table",
+	    "ft, text", /* keywords */
+	    NULL, /* requirements */
+	    WIDTH, HEIGHT,
+	    NULL, draw)
+
diff --git a/test/ft-text-antialias-none.c b/test/ft-text-antialias-none.c
index e139b2f..a6ab41c 100644
--- a/test/ft-text-antialias-none.c
+++ b/test/ft-text-antialias-none.c
@@ -33,15 +33,6 @@
 #define HEIGHT 30
 #define TEXT_SIZE 12
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "ft-text-antialias-none",
-    "Tests text rendering with no antialiasing",
-    WIDTH, HEIGHT,
-    draw
-};
-
 static cairo_status_t
 create_scaled_font (cairo_t * cr,
 		    cairo_scaled_font_t **out)
@@ -147,8 +138,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (ft_text_antialias_none,
+	    "Tests text rendering with no antialiasing",
+	    "ft, text", /* keywords */
+	    "target=raster", /* requirements */
+	    WIDTH, HEIGHT,
+	    NULL, draw)
diff --git a/test/ft-text-vertical-layout-type1.c b/test/ft-text-vertical-layout-type1.c
index 1dbe31d..28e81e0 100644
--- a/test/ft-text-vertical-layout-type1.c
+++ b/test/ft-text-vertical-layout-type1.c
@@ -33,16 +33,6 @@
 #define HEIGHT 240
 #define TEXT_SIZE 30
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "ft-text-vertical-layout-type1",
-    "Tests text rendering for vertical layout with Type1 fonts"
-    "\nCan fail if an incorrect font is loaded---need to bundle the desired font",
-    WIDTH, HEIGHT,
-    draw
-};
-
 static cairo_status_t
 create_scaled_font (cairo_t * cr,
 		    cairo_scaled_font_t **out)
@@ -169,8 +159,11 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (ft_text_vertical_layout_type1,
+	    "Tests text rendering for vertical layout with Type1 fonts"
+	    "\nCan fail if an incorrect font is loaded---need to bundle the desired font",
+	    "ft, text", /* keywords */
+	    NULL, /* requirements */
+	    WIDTH, HEIGHT,
+	    NULL, draw)
+
diff --git a/test/ft-text-vertical-layout-type3.c b/test/ft-text-vertical-layout-type3.c
index 0f85d73..36a0755 100644
--- a/test/ft-text-vertical-layout-type3.c
+++ b/test/ft-text-vertical-layout-type3.c
@@ -33,15 +33,6 @@
 #define HEIGHT 200
 #define TEXT_SIZE 30
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "ft-text-vertical-layout-type3",
-    "Tests text rendering for vertical layout with TrueType fonts",
-    WIDTH, HEIGHT,
-    draw
-};
-
 static cairo_status_t
 create_scaled_font (cairo_t * cr,
 		    cairo_scaled_font_t **out)
@@ -168,8 +159,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (ft_text_vertical_layout_type3,
+	    "Tests text rendering for vertical layout with TrueType fonts",
+	    "ft, text", /* keywords */
+	    NULL, /* requirements */
+	    WIDTH, HEIGHT,
+	    NULL, draw)
diff --git a/test/get-and-set.c b/test/get-and-set.c
index 90c394a..6a395d6 100644
--- a/test/get-and-set.c
+++ b/test/get-and-set.c
@@ -26,15 +26,6 @@
 
 #include "cairo-test.h"
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "get-and-set",
-    "Tests calls to the most trivial cairo_get and cairo_set functions",
-    0, 0,
-    draw
-};
-
 typedef struct {
     cairo_operator_t op;
     double tolerance;
@@ -160,8 +151,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (get_and_set,
+	    "Tests calls to the most trivial cairo_get and cairo_set functions",
+	    "api", /* keywords */
+	    NULL, /* requirements */
+	    0, 0,
+	    NULL, draw)
diff --git a/test/get-clip.c b/test/get-clip.c
index 5e0ff17..e246671 100644
--- a/test/get-clip.c
+++ b/test/get-clip.c
@@ -26,15 +26,6 @@
 #include "cairo-test.h"
 #include <stddef.h>
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "get-clip",
-    "Test cairo_copy_clip_rectangle_list and cairo_clip_extents",
-    0, 0,
-    draw
-};
-
 static cairo_bool_t
 check_count (const cairo_test_context_t *ctx,
 	     const char *message, cairo_bool_t uses_clip_rects,
@@ -138,6 +129,7 @@ draw (cairo_t *cr, int width, int height)
     case CAIRO_SURFACE_TYPE_WIN32:
     case CAIRO_SURFACE_TYPE_BEOS:
     case CAIRO_SURFACE_TYPE_DIRECTFB:
+    case CAIRO_SURFACE_TYPE_SDL:
         uses_clip_rects = TRUE;
 	break;
     case CAIRO_SURFACE_TYPE_QUARTZ:
@@ -283,8 +275,9 @@ FAIL:
     return cairo_test_status_from_status (ctx, status);
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (get_clip,
+	    "Test cairo_copy_clip_rectangle_list and cairo_clip_extents",
+	    "clip, extents", /* keywords */
+	    NULL, /* requirements */
+	    0, 0,
+	    NULL, draw)
diff --git a/test/get-group-target.c b/test/get-group-target.c
index 010f6ec..5aff19b 100644
--- a/test/get-group-target.c
+++ b/test/get-group-target.c
@@ -28,15 +28,6 @@
 #define SIZE 8
 #define PAD 2
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "get-group-target",
-    "Test of both cairo_get_group_target and cairo_surface_get_device_offset",
-    SIZE, SIZE,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -86,8 +77,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (get_group_target,
+	    "Test of both cairo_get_group_target and cairo_surface_get_device_offset",
+	    "api", /* keywords */
+	    NULL, /* requirements */
+	    SIZE, SIZE,
+	    NULL, draw)
diff --git a/test/get-path-extents.c b/test/get-path-extents.c
index 5bfdcd7..ce1bc7c 100644
--- a/test/get-path-extents.c
+++ b/test/get-path-extents.c
@@ -27,15 +27,6 @@
 #include <stddef.h>
 #include <math.h>
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "get-path-extents",
-    "Test cairo_fill_extents and cairo_stroke_extents",
-    0, 0,
-    draw
-};
-
 enum ExtentsType { FILL, STROKE, PATH };
 
 enum Relation { EQUALS, APPROX_EQUALS, CONTAINS };
@@ -379,8 +370,9 @@ draw (cairo_t *cr, int width, int height)
     return errors == 0 ? CAIRO_TEST_SUCCESS : CAIRO_TEST_FAILURE;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (get_path_extents,
+	    "Test cairo_fill_extents and cairo_stroke_extents",
+	    "extents, path", /* keywords */
+	    NULL, /* requirements */
+	    0, 0,
+	    NULL, draw)
diff --git a/test/get-xrender-format.c b/test/get-xrender-format.c
index 24f9035..8e99eb7 100644
--- a/test/get-xrender-format.c
+++ b/test/get-xrender-format.c
@@ -31,10 +31,9 @@
 
 #include "cairo-boilerplate-xlib.h"
 
-int
-main (void)
+static cairo_test_status_t
+preamble (cairo_test_context_t *ctx)
 {
-    cairo_test_context_t ctx;
     Display *dpy;
     XRenderPictFormat *orig_format, *format;
     cairo_surface_t *surface;
@@ -44,13 +43,12 @@ main (void)
 
     result = CAIRO_TEST_UNTESTED;
 
-    cairo_test_init (&ctx, "get-xrender-format");
-    if (! cairo_test_is_target_enabled (&ctx, "xlib"))
+    if (! cairo_test_is_target_enabled (ctx, "xlib"))
 	goto CLEANUP_TEST;
 
     dpy = XOpenDisplay (NULL);
     if (! dpy) {
-	cairo_test_log (&ctx, "Error: Cannot open display: %s, skipping.\n",
+	cairo_test_log (ctx, "Error: Cannot open display: %s, skipping.\n",
 			XDisplayName (NULL));
 	goto CLEANUP_TEST;
     }
@@ -59,19 +57,19 @@ main (void)
 
     screen = DefaultScreen (dpy);
 
-    cairo_test_log (&ctx, "Testing with image surface.\n");
+    cairo_test_log (ctx, "Testing with image surface.\n");
 
     surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 1, 1);
 
     format = cairo_xlib_surface_get_xrender_format (surface);
     if (format != NULL) {
-	cairo_test_log (&ctx, "Error: expected NULL for image surface\n");
+	cairo_test_log (ctx, "Error: expected NULL for image surface\n");
 	goto CLEANUP_SURFACE;
     }
 
     cairo_surface_destroy (surface);
 
-    cairo_test_log (&ctx, "Testing with non-xrender xlib surface.\n");
+    cairo_test_log (ctx, "Testing with non-xrender xlib surface.\n");
 
     pixmap = XCreatePixmap (dpy, DefaultRootWindow (dpy),
 			    1, 1, DefaultDepth (dpy, screen));
@@ -81,13 +79,13 @@ main (void)
     orig_format = XRenderFindVisualFormat (dpy, DefaultVisual (dpy, screen));
     format = cairo_xlib_surface_get_xrender_format (surface);
     if (format != orig_format) {
-	cairo_test_log (&ctx, "Error: did not receive the same format as XRenderFindVisualFormat\n");
+	cairo_test_log (ctx, "Error: did not receive the same format as XRenderFindVisualFormat\n");
 	goto CLEANUP_PIXMAP;
     }
     cairo_surface_destroy (surface);
     XFreePixmap (dpy, pixmap);
 
-    cairo_test_log (&ctx, "Testing with xlib xrender surface.\n");
+    cairo_test_log (ctx, "Testing with xlib xrender surface.\n");
 
     orig_format = XRenderFindStandardFormat (dpy, PictStandardARGB32);
     pixmap = XCreatePixmap (dpy, DefaultRootWindow (dpy),
@@ -99,17 +97,17 @@ main (void)
 							     1, 1);
     format = cairo_xlib_surface_get_xrender_format (surface);
     if (format != orig_format) {
-	cairo_test_log (&ctx, "Error: did not receive the same format originally set\n");
+	cairo_test_log (ctx, "Error: did not receive the same format originally set\n");
 	goto CLEANUP_PIXMAP;
     }
 
-    cairo_test_log (&ctx, "Testing without the X Render extension.\n");
+    cairo_test_log (ctx, "Testing without the X Render extension.\n");
 
     cairo_boilerplate_xlib_surface_disable_render (surface);
 
     format = cairo_xlib_surface_get_xrender_format (surface);
     if (format != NULL) {
-	cairo_test_log (&ctx, "Error: did not receive a NULL format as expected\n");
+	cairo_test_log (ctx, "Error: did not receive a NULL format as expected\n");
 	goto CLEANUP_PIXMAP;
     }
 
@@ -123,7 +121,12 @@ main (void)
     XCloseDisplay (dpy);
 
   CLEANUP_TEST:
-    cairo_test_fini (&ctx);
-
     return result;
 }
+
+CAIRO_TEST (get_xrender_format,
+	    "Check XRender specific API",
+	    "xrender, api", /* keywords */
+	    NULL, /* requirements */
+	    0, 0,
+	    preamble, NULL)
diff --git a/test/glyph-cache-pressure.c b/test/glyph-cache-pressure.c
index f0ab7d1..9b0e3f3 100644
--- a/test/glyph-cache-pressure.c
+++ b/test/glyph-cache-pressure.c
@@ -49,15 +49,6 @@
  *   _cairo_sacled_font_freeze/thaw_cache functions for this).
  */
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "glyph-cache-pressure",
-    "Ensure that all backends behave well under artificial glyph cache pressure",
-    223, TEXT_SIZE + 4,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -82,8 +73,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (glyph_cache_pressure,
+	    "Ensure that all backends behave well under artificial glyph cache pressure",
+	    "stress", /* keywords */
+	    NULL, /* requirements */
+	    223, TEXT_SIZE + 4,
+	    NULL, draw)
diff --git a/test/gradient-alpha.c b/test/gradient-alpha.c
index 38a282f..24cd324 100644
--- a/test/gradient-alpha.c
+++ b/test/gradient-alpha.c
@@ -25,15 +25,6 @@
 
 #include "cairo-test.h"
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "gradient-alpha",
-    "Tests drawing of a gradient with various alpha values in the color stops\n",
-    10, 10,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -57,8 +48,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (gradient_alpha,
+	    "Tests drawing of a gradient with various alpha values in the color stops",
+	    "gradient, alpha", /* keywords */
+	    NULL, /* requirements */
+	    10, 10,
+	    NULL, draw)
diff --git a/test/gradient-constant-alpha.c b/test/gradient-constant-alpha.c
index 0607621..7640b6e 100644
--- a/test/gradient-constant-alpha.c
+++ b/test/gradient-constant-alpha.c
@@ -27,15 +27,6 @@
 
 #include "cairo-test.h"
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "gradient-constant-alpha",
-    "Tests drawing of a gradient with constant alpha values in the color stops\n",
-    10, 10,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -62,8 +53,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (gradient_constant_alpha,
+	    "Tests drawing of a gradient with constant alpha values in the color stops",
+	    "gradient, alpha", /* keywords */
+	    NULL,
+	    10, 10,
+	    NULL, draw)
diff --git a/test/gradient-zero-stops.c b/test/gradient-zero-stops.c
index 0605ed0..57a91c5 100644
--- a/test/gradient-zero-stops.c
+++ b/test/gradient-zero-stops.c
@@ -32,20 +32,11 @@
  *      https://bugzilla.mozilla.org/show_bug.cgi?id=407104
  */
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "gradient-zero-stops",
-    "Verifies that gradients with no stops dont cause problems.",
-    2, 2,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
     cairo_pattern_t *pat;
-    
+
     pat = cairo_pattern_create_linear (0., 0., 1., 1.);
     cairo_set_source (cr, pat);
     cairo_paint (cr);
@@ -59,8 +50,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (gradient_zero_stops,
+	    "Verifies that gradients with no stops don't cause problems.",
+	    "gradient", /* keywords */
+	    NULL, /* requirements */
+	    2, 2,
+	    NULL, draw)
diff --git a/test/group-paint.c b/test/group-paint.c
index 1f6b1f6..3854485 100644
--- a/test/group-paint.c
+++ b/test/group-paint.c
@@ -25,15 +25,6 @@
 
 #include "cairo-test.h"
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "group-paint",
-    "test push_group(); pop_group_to_source(); set_operator(SOURCE); paint();",
-    10, 10,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -49,8 +40,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (group_paint,
+	    "test push_group(); pop_group_to_source(); set_operator(SOURCE); paint();",
+	    "group", /* keywords */
+	    NULL, /* requirements */
+	    10, 10,
+	    NULL, draw)
diff --git a/test/huge-pattern.c b/test/huge-pattern.c
index cec12ff..9a74337 100644
--- a/test/huge-pattern.c
+++ b/test/huge-pattern.c
@@ -26,16 +26,6 @@
 
 #include "cairo-test.h"
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "huge-pattern",
-    "Test huge linear patterns"
-    "\nhuge patterns seem to not be drawn correctly",
-    600, 350,
-    draw
-};
-
 /* set this to 0.1 to make this test work */
 #define FACTOR 1
 
@@ -67,8 +57,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (huge_pattern,
+	    "Test huge linear patterns",
+	    "gradient", /* keywords */
+	    NULL, /* requirements */
+	    600, 350,
+	    NULL, draw)
diff --git a/test/image-surface-source.c b/test/image-surface-source.c
index e675ecd..c7c1fdc 100644
--- a/test/image-surface-source.c
+++ b/test/image-surface-source.c
@@ -25,7 +25,6 @@
 
 #include "cairo-test.h"
 
-#define NAME "image"
 #include "surface-source.c"
 
 static cairo_surface_t *
@@ -33,3 +32,10 @@ create_source_surface (int size)
 {
     return cairo_image_surface_create (CAIRO_FORMAT_ARGB32, size, size);
 }
+
+CAIRO_TEST (image_surface_source,
+	    "Test using a image surface as the source",
+	    "source", /* keywords */
+	    NULL, /* requirements */
+	    SIZE, SIZE,
+	    preamble, draw)
diff --git a/test/in-fill-empty-trapezoid.c b/test/in-fill-empty-trapezoid.c
index 9d846a3..15ef01d 100644
--- a/test/in-fill-empty-trapezoid.c
+++ b/test/in-fill-empty-trapezoid.c
@@ -35,10 +35,9 @@
 
 #include "cairo-test.h"
 
-int
-main (void)
+static cairo_test_status_t
+preamble (cairo_test_context_t *ctx)
 {
-    cairo_test_context_t ctx;
     int x,y;
     int width = 10;
     int height = 10;
@@ -46,14 +45,8 @@ main (void)
     cairo_t *cr;
     int false_positive_count = 0;
     cairo_status_t status;
-    char const * description =
-	"Test that the tessellator isn't producing obviously empty trapezoids";
     cairo_test_status_t ret;
 
-    cairo_test_init (&ctx, "in-fill-empty-trapezoid");
-    cairo_test_log (&ctx, "%s\n", description);
-    printf ("%s\n", description);
-
     surf = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
     cr = cairo_create (surf);
     cairo_surface_destroy (surf);
@@ -88,19 +81,24 @@ main (void)
     /* Check that everything went well. */
     ret = CAIRO_TEST_SUCCESS;
     if (CAIRO_STATUS_SUCCESS != status) {
-	cairo_test_log (&ctx, "Failed to create a test surface and path: %s\n",
+	cairo_test_log (ctx, "Failed to create a test surface and path: %s\n",
 			cairo_status_to_string (status));
 	ret = CAIRO_TEST_FAILURE;
     }
 
     if (0 != false_positive_count) {
-	cairo_test_log (&ctx, "Point sampling found %d false positives "
+	cairo_test_log (ctx, "Point sampling found %d false positives "
 			"from cairo_in_fill()\n",
 			false_positive_count);
 	ret = CAIRO_TEST_FAILURE;
     }
 
-    cairo_test_fini (&ctx);
-
     return ret;
 }
+
+CAIRO_TEST (in_fill_empty_trapezoid,
+	    "Test that the tessellator isn't producing obviously empty trapezoids",
+	    "in, trap", /* keywords */
+	    NULL, /* requirements */
+	    0, 0,
+	    preamble, NULL)
diff --git a/test/in-fill-trapezoid.c b/test/in-fill-trapezoid.c
index c44ffb8..6ff2fef 100644
--- a/test/in-fill-trapezoid.c
+++ b/test/in-fill-trapezoid.c
@@ -26,15 +26,6 @@
 
 #include "cairo-test.h"
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "in-fill-trapezoid",
-    "Test _cairo_trap_contains via cairo_in_fill",
-    0, 0,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -80,8 +71,9 @@ draw (cairo_t *cr, int width, int height)
     return ret;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (in_fill_trapezoid,
+	    "Test _cairo_trap_contains via cairo_in_fill",
+	    "in, trap", /* keywords */
+	    NULL, /* requirements */
+	    0, 0,
+	    NULL, draw)
diff --git a/test/infinite-join.c b/test/infinite-join.c
index c2c728f..a573f56 100644
--- a/test/infinite-join.c
+++ b/test/infinite-join.c
@@ -33,15 +33,6 @@
 
 #include "cairo-test.h"
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "infinite-join",
-    "Test case for infinite loop when stroking with round joins",
-    8, 8,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -70,11 +61,12 @@ draw (cairo_t *cr, int width, int height)
     cairo_line_to (cr, 18928, 13843);
     cairo_stroke (cr);
 
-    return 0;
+    return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (infinite_join,
+	    "Test case for infinite loop when stroking with round joins",
+	    "stroke", /* keywords */
+	    NULL,
+	    8, 8,
+	    NULL, draw)
diff --git a/test/invalid-matrix.c b/test/invalid-matrix.c
index be11336..43dd6ed 100644
--- a/test/invalid-matrix.c
+++ b/test/invalid-matrix.c
@@ -37,15 +37,6 @@
 #include <fenv.h>
 #endif
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "invalid-matrix",
-    "Test that all relevant public functions return CAIRO_STATUS_INVALID_MATRIX as appropriate",
-    0, 0,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -393,8 +384,9 @@ if ((status) == CAIRO_STATUS_SUCCESS) {							\
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (invalid_matrix,
+	    "Test that all relevant public functions return CAIRO_STATUS_INVALID_MATRIX as appropriate",
+	    "api, matrix", /* keywords */
+	    NULL, /* requirements */
+	    0, 0,
+	    NULL, draw)
diff --git a/test/large-clip.c b/test/large-clip.c
index 02fa93a..d2380de 100644
--- a/test/large-clip.c
+++ b/test/large-clip.c
@@ -27,15 +27,6 @@
 
 #define SIZE 100
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "large-clip",
-    "Incorrect clipping when the clip rectangle doesn't fit in 16 bits signed",
-    SIZE, SIZE,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -44,15 +35,16 @@ draw (cairo_t *cr, int width, int height)
 
     cairo_rectangle (cr, 0, 0, 65536 + 25, 65536 + 25);
     cairo_clip (cr);
-    
+
     cairo_set_source_rgb (cr, 1, 0, 0);
     cairo_paint (cr);
 
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (large_clip,
+	    "Incorrect clipping when the clip rectangle doesn't fit in 16 bits signed",
+	    "clip, stress", /* keywords */
+	    NULL, /* requirements */
+	    SIZE, SIZE,
+	    NULL, draw)
diff --git a/test/large-font.c b/test/large-font.c
index 63418e1..d9ba954 100644
--- a/test/large-font.c
+++ b/test/large-font.c
@@ -36,7 +36,7 @@
  *			https://bugzilla.redhat.com/show_bug.cgi?id=448104
  *
  * 2008-05-23: Carl Worth wrote this test for the cairo test suite to
- *             exercise the bug.k
+ *             exercise the bug.
  */
 
 #include "cairo-test.h"
@@ -45,15 +45,6 @@
 #define HEIGHT 800
 #define TEXT_SIZE 10000
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "large-font",
-    "Draws a very large font to exercise a glyph-positioning bug",
-    WIDTH, HEIGHT,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -74,8 +65,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (large_font,
+	    "Draws a very large font to exercise a glyph-positioning bug",
+	    "stress, font", /* keywords */
+	    NULL, /* requirements */
+	    WIDTH, HEIGHT,
+	    NULL, draw)
diff --git a/test/large-source.c b/test/large-source.c
index fc8f514..5b2254c 100644
--- a/test/large-source.c
+++ b/test/large-source.c
@@ -32,15 +32,6 @@
  *	https://bugzilla.mozilla.org/show_bug.cgi?id=424333
  */
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "large-source",
-    "Exercises mozilla bug 424333 - handling of massive images",
-    20, 20,
-    draw
-};
-
 #ifdef WORDS_BIGENDIAN
 #define RED_MASK 0xA0
 #define GREEN_MASK 0xA
@@ -99,8 +90,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (large_source,
+	    "Exercises mozilla bug 424333 - handling of massive images",
+	    "stress, source", /* keywords */
+	    NULL, /* requirements */
+	    20, 20,
+	    NULL, draw)
diff --git a/test/leaky-dash.c b/test/leaky-dash.c
index 2a76715..12e91ac 100644
--- a/test/leaky-dash.c
+++ b/test/leaky-dash.c
@@ -34,16 +34,6 @@
 #define WIDTH 71
 #define HEIGHT 28
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "leaky-dash",
-    "Exercises bug #4863 in which a dashed stroke leaks into half the rectangle being filled"
-    "\nknown bug (#4863) which has existed since the 1.0 release",
-    WIDTH, HEIGHT,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -65,8 +55,10 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (leaky_dash,
+	    "Exercises bug #4863 in which a dashed stroke leaks into half the rectangle being filled"
+	    "\nknown bug (#4863) which has existed since the 1.0 release",
+	    "dash, stroke", /* keywords */
+	    NULL, /* requirements */
+	    WIDTH, HEIGHT,
+	    NULL, draw)
diff --git a/test/leaky-dashed-rectangle.c b/test/leaky-dashed-rectangle.c
index b593991..25f5674 100644
--- a/test/leaky-dashed-rectangle.c
+++ b/test/leaky-dashed-rectangle.c
@@ -35,15 +35,6 @@
 #define WIDTH 60
 #define HEIGHT 60
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "leaky-dashed-rectangle",
-    "Exercises bug in which a dashed stroke leaks in from outside the surface",
-    WIDTH, HEIGHT,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -87,8 +78,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (leaky_dashed_rectangle,
+	    "Exercises bug in which a dashed stroke leaks in from outside the surface",
+	    "dash, stroke", /* keywords */
+	    NULL, /* requirements */
+	    WIDTH, HEIGHT,
+	    NULL, draw)
diff --git a/test/leaky-dashed-stroke.c b/test/leaky-dashed-stroke.c
index 55b99d6..457d7ce 100644
--- a/test/leaky-dashed-stroke.c
+++ b/test/leaky-dashed-stroke.c
@@ -32,15 +32,6 @@
 #define WIDTH 205
 #define HEIGHT 260
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "leaky-dashed-stroke",
-    "Exercises bug in which a dashed stroke leaks in from outside the surface",
-    WIDTH, HEIGHT,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -167,8 +158,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (leaky_dashed_stroke,
+	    "Exercises bug in which a dashed stroke leaks in from outside the surface",
+	    "dash, stroke", /* keywords */
+	    NULL, /* requirements */
+	    WIDTH, HEIGHT,
+	    NULL, draw)
diff --git a/test/leaky-polygon.c b/test/leaky-polygon.c
index fbe7475..0ea7094 100644
--- a/test/leaky-polygon.c
+++ b/test/leaky-polygon.c
@@ -56,15 +56,6 @@
 #define WIDTH 21
 #define HEIGHT 21
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "leaky-polygon",
-    "Exercises a corner case in the trapezoid rasterization in which pixels outside the trapezoids received a non-zero alpha",
-    WIDTH, HEIGHT,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -86,8 +77,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (leaky_polygon,
+	    "Exercises a corner case in the trapezoid rasterization in which pixels outside the trapezoids received a non-zero alpha",
+	    "fill, trap", /* keywords */
+	    NULL, /* requirements */
+	    WIDTH, HEIGHT,
+	    NULL, draw)
diff --git a/test/line-width-scale.c b/test/line-width-scale.c
index 523b7d1..68e1f11 100644
--- a/test/line-width-scale.c
+++ b/test/line-width-scale.c
@@ -52,15 +52,6 @@
 #define WIDTH (XSCALE * SPLINE * 6.0)
 #define HEIGHT (YSCALE * SPLINE * 2.0)
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "line-width-scale",
-    "Tests interaction of cairo_set_line_width with cairo_scale",
-    WIDTH, HEIGHT,
-    draw
-};
-
 static void
 spline_path (cairo_t *cr)
 {
@@ -181,8 +172,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (line_width_scale,
+	    "Tests interaction of cairo_set_line_width with cairo_scale",
+	    "stroke", /* keywords */
+	    NULL, /* requirements */
+	    WIDTH, HEIGHT,
+	    NULL, draw)
diff --git a/test/line-width-zero.c b/test/line-width-zero.c
index 449f435..c7ac8a0 100644
--- a/test/line-width-zero.c
+++ b/test/line-width-zero.c
@@ -33,15 +33,6 @@
  *	https://bugs.freedesktop.org/show_bug.cgi?id=10231
  */
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "line-width-zero",
-    "Test all stroke operations and all cap,join styles with line width of zero",
-    0, 0,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -72,8 +63,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (line_width_zero,
+	    "Test all stroke operations and all cap,join styles with line width of zero",
+	    "stroke", /* keywords */
+	    NULL, /* requirements */
+	    0, 0,
+	    NULL, draw)
diff --git a/test/line-width.c b/test/line-width.c
index b1e31ff..e612a93 100644
--- a/test/line-width.c
+++ b/test/line-width.c
@@ -30,15 +30,6 @@
 #define IMAGE_WIDTH 2 * LINE_LENGTH + 6
 #define IMAGE_HEIGHT ((LINES+4)*LINES)/2 + 2
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "line-width",
-    "Tests cairo_set_line_width",
-    IMAGE_WIDTH, IMAGE_HEIGHT,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -65,8 +56,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (line_width,
+	    "Tests cairo_set_line_width",
+	    "stroke", /* keywords */
+	    NULL, /* requirements */
+	    IMAGE_WIDTH, IMAGE_HEIGHT,
+	    NULL, draw)
diff --git a/test/linear-gradient-reflect.c b/test/linear-gradient-reflect.c
index 0f0dea6..8adb587 100644
--- a/test/linear-gradient-reflect.c
+++ b/test/linear-gradient-reflect.c
@@ -30,15 +30,6 @@
 #define WIDTH  50
 #define HEIGHT 50
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "linear-gradient-reflect",
-    "Tests the drawing of linear gradient with reflect",
-    WIDTH, HEIGHT,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -67,8 +58,10 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (linear_gradient_reflect,
+	    "Tests the drawing of linear gradient with reflect",
+	    "gradient", /* keywords */
+	    NULL, /* requirements */
+	    WIDTH, HEIGHT,
+	    NULL, draw)
+
diff --git a/test/linear-gradient.c b/test/linear-gradient.c
index 166f643..054d6ab 100644
--- a/test/linear-gradient.c
+++ b/test/linear-gradient.c
@@ -54,15 +54,6 @@ static const int n_stops[] = { 2, 3 };
 #define WIDTH  N_GRADIENT_ANGLES * UNIT_SIZE + (N_GRADIENT_ANGLES + 1) * PAD
 #define HEIGHT N_N_STOPS * N_ROTATE_ANGLES * UNIT_SIZE + (N_N_STOPS * N_ROTATE_ANGLES + 1) * PAD
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "linear-gradient",
-    "Tests the drawing of linear gradients\n",
-    WIDTH, HEIGHT,
-    draw
-};
-
 static void
 draw_unit (cairo_t *cr,
 	   double   gradient_angle,
@@ -133,8 +124,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (linear_gradient,
+	    "Tests the drawing of linear gradients",
+	    "gradient", /* keywords */
+	    NULL, /* requirements */
+	    WIDTH, HEIGHT,
+	    NULL, draw)
diff --git a/test/long-dashed-lines.c b/test/long-dashed-lines.c
index 788951c..cd940fb 100644
--- a/test/long-dashed-lines.c
+++ b/test/long-dashed-lines.c
@@ -25,15 +25,6 @@
 
 #include "cairo-test.h"
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "long-dashed-lines",
-    "Exercises _cairo_box_intersects_line_segment()",
-    60, 60,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -67,8 +58,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (long_dashed_lines,
+	    "Exercises _cairo_box_intersects_line_segment()",
+	    "dash, stroke, stress", /* keywords */
+	    NULL, /* requirements */
+	    60, 60,
+	    NULL, draw)
diff --git a/test/long-lines.c b/test/long-lines.c
index dfbbe0d..c3e6dd6 100644
--- a/test/long-lines.c
+++ b/test/long-lines.c
@@ -30,17 +30,6 @@
 #define SIZE		10
 #define LINE_NBR	6
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "long-lines",
-    "Test long lines"
-    "\nLong lines are not drawn due to the limitations of the internal 16.16 fixed-point coordinates",
-    SIZE * (LINE_NBR + 1),
-    SIZE * (LINE_NBR + 1),
-    draw
-};
-
 struct {
     double length;
     double red, green, blue;
@@ -85,8 +74,11 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (long_lines,
+	    "Test long lines"
+	    "\nLong lines are not drawn due to the limitations of the internal 16.16 fixed-point coordinates",
+	    "XFAIL stroke, stress", /* keywords */
+	    NULL, /* requirements */
+	    SIZE * (LINE_NBR + 1), SIZE * (LINE_NBR + 1),
+	    NULL, draw)
+
diff --git a/test/make-cairo-test-constructors.pl b/test/make-cairo-test-constructors.pl
new file mode 100755
index 0000000..5e77175
--- /dev/null
+++ b/test/make-cairo-test-constructors.pl
@@ -0,0 +1,18 @@
+#!/usr/bin/perl -w
+
+while (<>) {
+    next unless /CAIRO_TEST \((.*),/; # XXX Parse multi-line macro
+    push @names, $1;
+}
+
+print <<EOD
+/* WARNING: Autogenerated file - see make-cairo-test-constructors.pl! */
+
+#include "cairo-test-private.h"
+
+EOD
+;
+print "extern void _register_$_ (void);\n" foreach (@names);
+print "\nvoid\n_cairo_test_runner_register_tests (void)\n{\n";
+print "    _register_$_ ();\n" foreach (reverse @names);
+print "}\n";
diff --git a/test/mask-alpha.c b/test/mask-alpha.c
index 284e2cb..d66e0ac 100644
--- a/test/mask-alpha.c
+++ b/test/mask-alpha.c
@@ -26,8 +26,6 @@
 
 #include "cairo-test.h"
 
-static cairo_test_draw_function_t draw;
-
 #define SIZE 40
 #define PAD 2
 #define WIDTH (PAD + SIZE + PAD)
@@ -41,13 +39,6 @@ static cairo_test_draw_function_t draw;
  * (0.8, 0.8, 0.8, 0.4).
  */
 
-static const cairo_test_t test = {
-    "mask-alpha",
-    "A simple test painting a group through a circle mask",
-    WIDTH, HEIGHT,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -83,8 +74,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (mask_alpha,
+	    "A simple test painting a group through a circle mask",
+	    "mask, alpha", /* keywords */
+	    NULL, /* requirements */
+	    WIDTH, HEIGHT,
+	    NULL, draw)
diff --git a/test/mask-ctm.c b/test/mask-ctm.c
index c6814b0..7b3a394 100644
--- a/test/mask-ctm.c
+++ b/test/mask-ctm.c
@@ -25,15 +25,6 @@
 
 #include "cairo-test.h"
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "mask-ctm",
-    "Test that cairo_mask is affected properly by the CTM",
-    10, 10,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -78,8 +69,10 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (mask_ctm,
+	    "Test that cairo_mask is affected properly by the CTM",
+	    "mask", /* keywords */
+	    NULL, /* requirements */
+	    10, 10,
+	    NULL, draw)
+
diff --git a/test/mask-surface-ctm.c b/test/mask-surface-ctm.c
index f4a0c39..50f6d01 100644
--- a/test/mask-surface-ctm.c
+++ b/test/mask-surface-ctm.c
@@ -25,15 +25,6 @@
 
 #include "cairo-test.h"
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "mask-surface-ctm",
-    "Test that cairo_mask_surface is affected properly by the CTM",
-    10, 10,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -71,8 +62,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (mask_surface_ctm,
+	    "Test that cairo_mask_surface is affected properly by the CTM",
+	    "mask", /* keywords */
+	    NULL, /* requirements */
+	    10, 10,
+	    NULL, draw)
diff --git a/test/mask-transformed-image.c b/test/mask-transformed-image.c
index 84901e7..13c8fe7 100644
--- a/test/mask-transformed-image.c
+++ b/test/mask-transformed-image.c
@@ -26,16 +26,8 @@
 
 #include "cairo-test.h"
 
-static cairo_test_draw_function_t draw;
 static const char png_filename[] = "romedalen.png";
 
-static const cairo_test_t test = {
-    "mask-transformed-image",
-    "Test that cairo_mask() is affected properly by the CTM and not the image",
-    80, 80,
-    draw
-};
-
 static cairo_surface_t *
 create_mask (cairo_t *dst, int width, int height)
 {
@@ -96,8 +88,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (mask_transformed_image,
+	    "Test that cairo_mask() is affected properly by the CTM and not the image",
+	    "mask", /* keywords */
+	    NULL, /* requirements */
+	    80, 80,
+	    NULL, draw)
diff --git a/test/mask-transformed-similar.c b/test/mask-transformed-similar.c
index ea28ea4..c37deb2 100644
--- a/test/mask-transformed-similar.c
+++ b/test/mask-transformed-similar.c
@@ -26,16 +26,8 @@
 
 #include "cairo-test.h"
 
-static cairo_test_draw_function_t draw;
 static const char png_filename[] = "romedalen.png";
 
-static const cairo_test_t test = {
-    "mask-transformed-similar",
-    "Test that cairo_mask() is affected properly by the CTM and not the image",
-    80, 80,
-    draw
-};
-
 static cairo_surface_t *
 create_mask (cairo_t *dst, int width, int height)
 {
@@ -98,8 +90,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (mask_transformed_similar,
+	    "Test that cairo_mask() is affected properly by the CTM and not the image",
+	    "mask", /* keywords */
+	    NULL, /* requirements */
+	    80, 80,
+	    NULL, draw)
diff --git a/test/mask.c b/test/mask.c
index ec7cb8f..bc1adfd 100644
--- a/test/mask.c
+++ b/test/mask.c
@@ -32,7 +32,7 @@
 #define HEIGHT 16
 #define PAD 2
 
-static const char	png_filename[]	= "romedalen.png";
+static const char *png_filename = "romedalen.png";
 
 static void
 set_solid_pattern (const cairo_test_context_t *ctx, cairo_t *cr, int x, int y)
@@ -177,15 +177,6 @@ static void (* const clip_funcs[])(cairo_t *cr, int x, int y) = {
 #define IMAGE_WIDTH (ARRAY_SIZE (pattern_funcs) * (WIDTH + PAD) + PAD)
 #define IMAGE_HEIGHT (ARRAY_SIZE (mask_funcs) * ARRAY_SIZE (clip_funcs) * (HEIGHT + PAD) + PAD)
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "mask",
-    "Tests of cairo_mask",
-    IMAGE_WIDTH, IMAGE_HEIGHT,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -237,8 +228,10 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (mask,
+	    "Tests of cairo_mask",
+	    "mask", /* keywords */
+	    NULL, /* requirements */
+	    IMAGE_WIDTH, IMAGE_HEIGHT,
+	    NULL, draw)
+
diff --git a/test/meta-surface-pattern.c b/test/meta-surface-pattern.c
index 0eea61d..9fd1235 100644
--- a/test/meta-surface-pattern.c
+++ b/test/meta-surface-pattern.c
@@ -26,8 +26,6 @@
 
 #include "cairo-test.h"
 
-static cairo_test_draw_function_t draw;
-
 #define PAT_WIDTH  120
 #define PAT_HEIGHT 120
 #define SIZE (PAT_WIDTH*2)
@@ -40,13 +38,6 @@ static cairo_test_draw_function_t draw;
  * CAIRO_EXTEND_NONE and a non identity pattern matrix.
  */
 
-static const cairo_test_t test = {
-    "meta-surface-pattern",
-    "Paint meta surface pattern with non identity pattern matrix",
-    WIDTH, HEIGHT,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -122,8 +113,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (meta_surface_pattern,
+	    "Paint meta surface pattern with non identity pattern matrix",
+	    "meta", /* keywords */
+	    NULL, /* requirements */
+	    WIDTH, HEIGHT,
+	    NULL, draw)
diff --git a/test/miter-precision.c b/test/miter-precision.c
index a4e5f2e..3e8f731 100644
--- a/test/miter-precision.c
+++ b/test/miter-precision.c
@@ -33,16 +33,6 @@
  */
 #include "cairo-test.h"
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "miter-precision",
-    "test how cairo deals with small miters"
-    "\nPS backend currently fails due to GS bug.",
-    120, 100,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -73,8 +63,10 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (miter_precision,
+	    "test how cairo deals with small miters"
+	    "\ncurrent code draws inappropriate bevels at times",
+	    "stoke, stress", /* keywords */
+	    NULL, /* requirements */
+	    120, 100,
+	    NULL, draw)
diff --git a/test/move-to-show-surface.c b/test/move-to-show-surface.c
index e017fa6..6caad1b 100644
--- a/test/move-to-show-surface.c
+++ b/test/move-to-show-surface.c
@@ -45,15 +45,6 @@
 
 #include "cairo-test.h"
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "move-to-show-surface",
-    "Tests calls to cairo_show_surface after cairo_move_to",
-    2, 2,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -77,8 +68,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (move_to_show_surface,
+	    "Tests calls to cairo_show_surface after cairo_move_to",
+	    "transform", /* keywords */
+	    NULL, /* requirements */
+	    2, 2,
+	    NULL, draw)
diff --git a/test/multi-page.c b/test/multi-page.c
index 5000280..89f00c7 100644
--- a/test/multi-page.c
+++ b/test/multi-page.c
@@ -127,30 +127,27 @@ draw_some_pages (cairo_surface_t *surface)
     cairo_destroy (cr);
 }
 
-int
-main (void)
+static cairo_test_status_t
+preamble (cairo_test_context_t *ctx)
 {
-    cairo_test_context_t ctx;
     cairo_surface_t *surface;
     cairo_status_t status;
     const char *filename;
     cairo_test_status_t result = CAIRO_TEST_UNTESTED;
 
-    cairo_test_init (&ctx, "multi-page");
-
 #if CAIRO_HAS_PS_SURFACE
-    if (cairo_test_is_target_enabled (&ctx, "ps2") ||
-        cairo_test_is_target_enabled (&ctx, "ps3"))
+    if (cairo_test_is_target_enabled (ctx, "ps2") ||
+        cairo_test_is_target_enabled (ctx, "ps3"))
     {
 	if (result == CAIRO_TEST_UNTESTED)
 	    result = CAIRO_TEST_SUCCESS;
 
-	filename = "multi-page.ps";
+	filename = "multi-page-out.ps";
 	surface = cairo_ps_surface_create (filename,
 					   WIDTH_IN_POINTS, HEIGHT_IN_POINTS);
 	status = cairo_surface_status (surface);
 	if (status) {
-	    cairo_test_log (&ctx, "Failed to create ps surface for file %s: %s\n",
+	    cairo_test_log (ctx, "Failed to create ps surface for file %s: %s\n",
 			    filename, cairo_status_to_string (status));
 	    result = CAIRO_TEST_FAILURE;
 	}
@@ -164,16 +161,16 @@ main (void)
 #endif
 
 #if CAIRO_HAS_PDF_SURFACE
-    if (cairo_test_is_target_enabled (&ctx, "pdf")) {
+    if (cairo_test_is_target_enabled (ctx, "pdf")) {
 	if (result == CAIRO_TEST_UNTESTED)
 	    result = CAIRO_TEST_SUCCESS;
 
-	filename = "multi-page.pdf";
+	filename = "multi-page-out.pdf";
 	surface = cairo_pdf_surface_create (filename,
 					    WIDTH_IN_POINTS, HEIGHT_IN_POINTS);
 	status = cairo_surface_status (surface);
 	if (status) {
-	    cairo_test_log (&ctx, "Failed to create pdf surface for file %s: %s\n",
+	    cairo_test_log (ctx, "Failed to create pdf surface for file %s: %s\n",
 			    filename, cairo_status_to_string (status));
 	    result = CAIRO_TEST_FAILURE;
 	}
@@ -186,7 +183,12 @@ main (void)
     }
 #endif
 
-    cairo_test_fini (&ctx);
-
     return result;
 }
+
+CAIRO_TEST (multi_page,
+	    "Check the paginated surfaces handle multiple pages.",
+	    "paginated", /* keywords */
+	    "target=vector", /* requirements */
+	    0, 0,
+	    preamble, NULL)
diff --git a/test/new-sub-path.c b/test/new-sub-path.c
index 19beaed..f8f6bbe 100644
--- a/test/new-sub-path.c
+++ b/test/new-sub-path.c
@@ -27,16 +27,6 @@
 
 #define SIZE 10
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "new-sub-path",
-    "Test the cairo_new_sub_path call",
-    8 * SIZE,
-    3 * SIZE,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -75,8 +65,10 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (new_sub_path,
+	    "Test the cairo_new_sub_path call",
+	    "path", /* keywords */
+	    NULL, /* requirements */
+	    8 * SIZE,
+	    3 * SIZE,
+	    NULL, draw)
diff --git a/test/nil-surface.c b/test/nil-surface.c
index b2070fe..408bdba 100644
--- a/test/nil-surface.c
+++ b/test/nil-surface.c
@@ -33,15 +33,6 @@
  *	https://bugs.freedesktop.org/show_bug.cgi?id=9906
  */
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "nil-surface",
-    "Test that nil surfaces do not make cairo crash.",
-    1, 1,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -170,8 +161,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (nil_surface,
+	    "Test that nil surfaces do not make cairo crash.",
+	    "api", /* keywords */
+	    NULL, /* requirements */
+	    1, 1,
+	    NULL, draw)
diff --git a/test/operator-alpha.c b/test/operator-alpha.c
index 28dc7cb..473ef20 100644
--- a/test/operator-alpha.c
+++ b/test/operator-alpha.c
@@ -29,15 +29,6 @@
 #define SIZE 10
 #define PAD 3
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "operator-alpha",
-    "Tests using set_operator() with an non-opaque source",
-    (SIZE+PAD) * N_OPERATORS + PAD, SIZE + 2*PAD,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -66,9 +57,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
-
+CAIRO_TEST (operator_alpha,
+	    "Tests using set_operator() with an non-opaque source",
+	    "XFAIL=svg12 operator, alpha", /* keywords */
+	    NULL, /* requirements */
+	    (SIZE+PAD) * N_OPERATORS + PAD, SIZE + 2*PAD,
+	    NULL, draw)
diff --git a/test/operator-clear.c b/test/operator-clear.c
index d6c4d30..7ce8535 100644
--- a/test/operator-clear.c
+++ b/test/operator-clear.c
@@ -142,15 +142,6 @@ static void (* const draw_funcs[])(cairo_t *cr, int x, int y) = {
 #define IMAGE_WIDTH (ARRAY_SIZE (pattern_funcs) * (WIDTH + PAD) + PAD)
 #define IMAGE_HEIGHT (ARRAY_SIZE (draw_funcs) * (HEIGHT + PAD) + PAD)
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "operator-clear",
-    "Test of CAIRO_OPERATOR_CLEAR",
-    IMAGE_WIDTH, IMAGE_HEIGHT,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -198,8 +189,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (operator_clear,
+	    "Test of CAIRO_OPERATOR_CLEAR",
+	    "XFAIL=svg12 operator", /* keywords */
+	    NULL, /* requirements */
+	    IMAGE_WIDTH, IMAGE_HEIGHT,
+	    NULL, draw)
diff --git a/test/operator-source.c b/test/operator-source.c
index b4968ad..ee115d0 100644
--- a/test/operator-source.c
+++ b/test/operator-source.c
@@ -179,15 +179,6 @@ static void (* const draw_funcs[])(cairo_t *cr, int x, int y) = {
 #define IMAGE_WIDTH (ARRAY_SIZE (pattern_funcs) * (WIDTH + PAD) + PAD)
 #define IMAGE_HEIGHT (ARRAY_SIZE (draw_funcs) * (HEIGHT + PAD) + PAD)
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "operator-source",
-    "Test of CAIRO_OPERATOR_SOURCE",
-    IMAGE_WIDTH, IMAGE_HEIGHT,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -235,8 +226,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (operator_source,
+	    "Test of CAIRO_OPERATOR_SOURCE",
+	    "XFAIL=svg12 operator", /* keywords */
+	    NULL, /* requirements */
+	    IMAGE_WIDTH, IMAGE_HEIGHT,
+	    NULL, draw)
diff --git a/test/operator.c b/test/operator.c
index bb269b2..39596e1 100644
--- a/test/operator.c
+++ b/test/operator.c
@@ -29,15 +29,6 @@
 #define SIZE 10
 #define PAD 3
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "operator",
-    "Tests using set_operator()",
-    (SIZE+PAD) * N_OPERATORS + PAD, SIZE + 2*PAD,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -66,9 +57,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
-
+CAIRO_TEST (operator,
+	    "Tests using set_operator()",
+	    "XFAIL=svg12 operator", /* keywords */
+	    NULL, /* requirements */
+	    (SIZE+PAD) * N_OPERATORS + PAD, SIZE + 2*PAD,
+	    NULL, draw)
diff --git a/test/over-above-source.c b/test/over-above-source.c
index 928fb36..1a47aae 100644
--- a/test/over-above-source.c
+++ b/test/over-above-source.c
@@ -26,8 +26,6 @@
 
 #include "cairo-test.h"
 
-static cairo_test_draw_function_t draw;
-
 #define SIZE 40
 #define PAD 2
 #define WIDTH (PAD + SIZE + PAD)
@@ -39,13 +37,6 @@ static cairo_test_draw_function_t draw;
  * surface, it's the reverse where OVER is native while SOURCE is a
  * fallback. */
 
-static const cairo_test_t test = {
-    "over-above-source",
-    "A simple test drawing a circle with OVER after a triangle drawn with SOURCE",
-    WIDTH, HEIGHT,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -73,8 +64,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (over_above_source,
+	    "A simple test drawing a circle with OVER after a triangle drawn with SOURCE",
+	    "XFAIL=svg12 operator", /* keywords */
+	    NULL, /* requirements */
+	    WIDTH, HEIGHT,
+	    NULL, draw)
diff --git a/test/over-around-source.c b/test/over-around-source.c
index 030e42d..7ac68a1 100644
--- a/test/over-around-source.c
+++ b/test/over-around-source.c
@@ -26,8 +26,6 @@
 
 #include "cairo-test.h"
 
-static cairo_test_draw_function_t draw;
-
 #define SIZE 40
 #define PAD 2
 #define WIDTH (PAD + SIZE + PAD)
@@ -39,13 +37,6 @@ static cairo_test_draw_function_t draw;
  * surface, it's the reverse where OVER is native while SOURCE is a
  * fallback. */
 
-static const cairo_test_t test = {
-    "over-around-source",
-    "A simple test drawing a triangle with SOURCE between two circles drawn with OVER",
-    WIDTH, HEIGHT,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -84,8 +75,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (over_around_source,
+	    "A simple test drawing a triangle with SOURCE between two circles drawn with OVER",
+	    "XFAIL=svg12 operator", /* keywords */
+	    NULL, /* requirements */
+	    WIDTH, HEIGHT,
+	    NULL, draw)
diff --git a/test/over-below-source.c b/test/over-below-source.c
index 74dac6f..36dc9cc 100644
--- a/test/over-below-source.c
+++ b/test/over-below-source.c
@@ -26,8 +26,6 @@
 
 #include "cairo-test.h"
 
-static cairo_test_draw_function_t draw;
-
 #define SIZE 40
 #define PAD 2
 #define WIDTH (PAD + SIZE + PAD)
@@ -39,13 +37,6 @@ static cairo_test_draw_function_t draw;
  * surface, it's the reverse where OVER is native while SOURCE is a
  * fallback. */
 
-static const cairo_test_t test = {
-    "over-below-source",
-    "A simple test drawing a circle with OVER before a triangle drawn with SOURCE",
-    WIDTH, HEIGHT,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -73,8 +64,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (over_below_source,
+	    "A simple test drawing a circle with OVER before a triangle drawn with SOURCE",
+	    "XFAIL=svg12 operator", /* keywords */
+	    NULL, /* requirements */
+	    WIDTH, HEIGHT,
+	    NULL, draw)
diff --git a/test/over-between-source.c b/test/over-between-source.c
index f88b6cc..e690cdd 100644
--- a/test/over-between-source.c
+++ b/test/over-between-source.c
@@ -26,8 +26,6 @@
 
 #include "cairo-test.h"
 
-static cairo_test_draw_function_t draw;
-
 #define SIZE 40
 #define PAD 2
 #define WIDTH (PAD + SIZE + PAD)
@@ -39,13 +37,6 @@ static cairo_test_draw_function_t draw;
  * surface, it's the reverse where OVER is native while SOURCE is a
  * fallback. */
 
-static const cairo_test_t test = {
-    "over-between-source",
-    "A simple test drawing a circle with OVER between two triangles drawn with SOURCE",
-    WIDTH, HEIGHT,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -84,8 +75,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (over_between_source,
+	    "A simple test drawing a circle with OVER between two triangles drawn with SOURCE",
+	    "XFAIL=12 operator", /* keywords */
+	    NULL, /* requirements */
+	    WIDTH, HEIGHT,
+	    NULL, draw)
diff --git a/test/paint-repeat.c b/test/paint-repeat.c
index 8e7f4ab..35b383c 100644
--- a/test/paint-repeat.c
+++ b/test/paint-repeat.c
@@ -25,15 +25,6 @@
 
 #include "cairo-test.h"
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "paint-repeat",
-    "Test calls to cairo_paint with a repeating source surface pattern",
-    8, 8,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -61,8 +52,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (paint_repeat,
+	    "Test calls to cairo_paint with a repeating source surface pattern",
+	    "paint", /* keywords */
+	    NULL, /* requirements */
+	    8, 8,
+	    NULL, draw)
diff --git a/test/paint-source-alpha.c b/test/paint-source-alpha.c
index 764b744..ecddc48 100644
--- a/test/paint-source-alpha.c
+++ b/test/paint-source-alpha.c
@@ -26,15 +26,6 @@
 
 #include "cairo-test.h"
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "paint-source-alpha",
-    "Simple test of cairo_paint with a source surface with non-opaque alpha",
-    32, 32,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -63,8 +54,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (paint_source_alpha,
+	    "Simple test of cairo_paint with a source surface with non-opaque alpha",
+	    "XFAIL=svg12 paint, alpha", /* keywords */
+	    NULL, /* requirements */
+	    32, 32,
+	    NULL, draw)
diff --git a/test/paint-with-alpha.c b/test/paint-with-alpha.c
index adfb7ce..678d313 100644
--- a/test/paint-with-alpha.c
+++ b/test/paint-with-alpha.c
@@ -26,15 +26,6 @@
 
 #include "cairo-test.h"
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "paint-with-alpha",
-    "Simple test of cairo_paint_with_alpha",
-    32, 32,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -63,8 +54,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (paint_with_alpha,
+	    "Simple test of cairo_paint_with_alpha",
+	    "paint, alpha", /* keywords */
+	    NULL, /* requirements */
+	    32, 32,
+	    NULL, draw)
diff --git a/test/paint.c b/test/paint.c
index 6f5ecf2..c5fd648 100644
--- a/test/paint.c
+++ b/test/paint.c
@@ -25,15 +25,6 @@
 
 #include "cairo-test.h"
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "paint",
-    "Test calls to cairo_paint",
-    8, 8,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -49,8 +40,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (paint,
+	    "Test calls to cairo_paint",
+	    "paint", /* keywords */
+	    NULL, /* requirements */
+	    8, 8,
+	    NULL, draw)
diff --git a/test/pattern-get-type.c b/test/pattern-get-type.c
index 96ed0c9..d2ef5bf 100644
--- a/test/pattern-get-type.c
+++ b/test/pattern-get-type.c
@@ -25,17 +25,13 @@
 
 #include "cairo-test.h"
 
-int
-main (void)
+static cairo_test_status_t
+preamble (cairo_test_context_t *Ctx)
 {
-    cairo_test_context_t ctx;
     cairo_surface_t *surface;
     cairo_pattern_t *solid_rgb, *solid_rgba, *surface_pattern, *linear, *radial;
     cairo_test_status_t result = CAIRO_TEST_SUCCESS;
 
-    cairo_test_init (&ctx, "pattern-get-type");
-    cairo_test_log (&ctx, "Creating patterns of all types\n");
-
     solid_rgb = cairo_pattern_create_rgb (0.0, 0.1, 0.2);
     solid_rgba = cairo_pattern_create_rgba (0.3, 0.4, 0.5, 0.6);
     surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
@@ -45,8 +41,6 @@ main (void)
     radial = cairo_pattern_create_radial (10.0, 10.0, 0.1,
 					  10.0, 10.0, 1.0);
 
-    cairo_test_log (&ctx, "Verifying return values of cairo_pattern_get_type\n");
-
     if (cairo_pattern_get_type (solid_rgb) != CAIRO_PATTERN_TYPE_SOLID)
 	result = CAIRO_TEST_FAILURE;
 
@@ -62,8 +56,6 @@ main (void)
     if (cairo_pattern_get_type (radial) != CAIRO_PATTERN_TYPE_RADIAL)
 	result = CAIRO_TEST_FAILURE;
 
-    cairo_test_log (&ctx, "Cleaning up\n");
-
     cairo_pattern_destroy (solid_rgb);
     cairo_pattern_destroy (solid_rgba);
     cairo_pattern_destroy (surface_pattern);
@@ -71,7 +63,12 @@ main (void)
     cairo_pattern_destroy (linear);
     cairo_pattern_destroy (radial);
 
-    cairo_test_fini (&ctx);
-
     return result;
 }
+
+CAIRO_TEST (pattern_get_type,
+	    "Creating patterns of all types",
+	    "pattern, api", /* keywords */
+	    NULL, /* requirements */
+	    0, 0,
+	    preamble, NULL)
diff --git a/test/pattern-getters.c b/test/pattern-getters.c
index a42d47b..0b9c86b 100644
--- a/test/pattern-getters.c
+++ b/test/pattern-getters.c
@@ -27,15 +27,6 @@
 #include <stdlib.h>
 #include "cairo-test.h"
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "pattern-getters",
-    "Tests calls to pattern getter functions",
-    1, 1,
-    draw
-};
-
 #define CHECK_SUCCESS do { if (status) return CAIRO_TEST_FAILURE; } while (0)
 
 static int
@@ -177,8 +168,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (pattern_getters,
+	    "Tests calls to pattern getter functions",
+	    "pattern, api", /* keywords */
+	    NULL, /* requirements */
+	    1, 1,
+	    NULL, draw)
diff --git a/test/pdf-features.c b/test/pdf-features.c
index e861685..dbfa332 100644
--- a/test/pdf-features.c
+++ b/test/pdf-features.c
@@ -42,7 +42,7 @@
 
 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0]))
 
-struct {
+static struct {
     const char *page_size;
     const char *page_size_alias;
     const char *orientation;
@@ -83,23 +83,17 @@ struct {
      MM_TO_POINTS(37), MM_TO_POINTS(26)}
 };
 
-int
-main (void)
+static cairo_test_status_t
+preamble (cairo_test_context_t *ctx)
 {
-    cairo_test_context_t ctx;
+    const char *filename = "pdf-features-out.pdf";
     cairo_surface_t *surface;
     cairo_t *cr;
     cairo_status_t status;
-    const char *filename;
     size_t i;
 
-    cairo_test_init (&ctx, "pdf-features");
-    if (! cairo_test_is_target_enabled (&ctx, "pdf")) {
-	cairo_test_fini (&ctx);
+    if (! cairo_test_is_target_enabled (ctx, "pdf"))
 	return CAIRO_TEST_UNTESTED;
-    }
-
-    filename = "pdf-features.pdf";
 
     /* The initial size passed here is the default size that will be
      * inheritable by each page. That is, any page for which this
@@ -116,8 +110,7 @@ main (void)
 			    CAIRO_FONT_WEIGHT_NORMAL);
     cairo_set_font_size (cr, TEXT_SIZE);
 
-    for (i=0; i < ARRAY_SIZE(pages); i++)
-    {
+    for (i = 0; i < ARRAY_SIZE (pages); i++) {
 	cairo_pdf_surface_set_size (surface,
 				   pages[i].width_in_points,
 				   pages[i].height_in_points);
@@ -135,14 +128,18 @@ main (void)
     cairo_surface_destroy (surface);
 
     if (status) {
-	cairo_test_log (&ctx, "Failed to create pdf surface for file %s: %s\n",
+	cairo_test_log (ctx, "Failed to create pdf surface for file %s: %s\n",
 			filename, cairo_status_to_string (status));
 	return CAIRO_TEST_FAILURE;
     }
 
     printf ("pdf-features: Please check %s to ensure it looks/prints correctly.\n", filename);
-
-    cairo_test_fini (&ctx);
-
     return CAIRO_TEST_SUCCESS;
 }
+
+CAIRO_TEST (pdf_features,
+	    "Check PDF specific API",
+	    "pdf", /* keywords */
+	    NULL, /* requirements */
+	    0, 0,
+	    preamble, NULL)
diff --git a/test/pdf-surface-source.c b/test/pdf-surface-source.c
index 680eeef..23149a9 100644
--- a/test/pdf-surface-source.c
+++ b/test/pdf-surface-source.c
@@ -26,7 +26,6 @@
 #include "cairo-test.h"
 #include <cairo-pdf.h>
 
-#define NAME "pdf"
 #include "surface-source.c"
 
 static cairo_surface_t *
@@ -34,8 +33,15 @@ create_source_surface (int size)
 {
     cairo_surface_t *surface;
 
-    surface = cairo_pdf_surface_create ("pdf-surface-source.pdf", size, size);
+    surface = cairo_pdf_surface_create ("pdf-surface-source-out.pdf", size, size);
     cairo_surface_set_fallback_resolution (surface, 72., 72.);
 
     return surface;
 }
+
+CAIRO_TEST (pdf_surface_source,
+	    "Test using a PDF surface as the source",
+	    "source", /* keywords */
+	    NULL, /* requirements */
+	    SIZE, SIZE,
+	    preamble, draw)
diff --git a/test/pixman-rotate.c b/test/pixman-rotate.c
index 313b34d..f412ce6 100644
--- a/test/pixman-rotate.c
+++ b/test/pixman-rotate.c
@@ -39,15 +39,6 @@
 #define IMAGE_WIDTH	(3 * WIDTH)
 #define IMAGE_HEIGHT	IMAGE_WIDTH
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "pixman-rotate",
-    "Exposes pixman off-by-one error when rotating",
-    IMAGE_WIDTH, IMAGE_HEIGHT,
-    draw
-};
-
 /* Draw the word cairo at NUM_TEXT different angles */
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
@@ -93,8 +84,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (pixman_rotate,
+	    "Exposes pixman off-by-one error when rotating",
+	    "image, transform", /* keywords */
+	    NULL, /* requirements */
+	    IMAGE_WIDTH, IMAGE_HEIGHT,
+	    NULL, draw)
diff --git a/test/png.c b/test/png.c
index 23fc9fe..0a375cb 100644
--- a/test/png.c
+++ b/test/png.c
@@ -25,7 +25,6 @@
 
 #include "cairo-test.h"
 
-#include <cairo.h>
 #include <assert.h>
 
 /* Test the idempotency of write_png->read_png */
@@ -63,7 +62,7 @@ format_to_string (cairo_format_t format)
 }
 
 static void
-print_surface (cairo_test_context_t *ctx, cairo_surface_t *surface)
+print_surface (const cairo_test_context_t *ctx, cairo_surface_t *surface)
 {
     cairo_test_log (ctx,
 		    "%s (%dx%d)\n",
@@ -72,39 +71,37 @@ print_surface (cairo_test_context_t *ctx, cairo_surface_t *surface)
 		    cairo_image_surface_get_height (surface));
 }
 
-int
-main (void)
+static cairo_test_status_t
+preamble (cairo_test_context_t *ctx)
 {
-    cairo_test_context_t ctx;
+    const char *filename = "png-out.png";
     cairo_surface_t *surface0, *surface1;
     cairo_status_t status;
     uint32_t argb32 = 0xdeadbede;
     cairo_test_status_t result = CAIRO_TEST_SUCCESS;
 
-    cairo_test_init (&ctx, "png");
-
     surface0 = cairo_image_surface_create_for_data ((unsigned char *) &argb32,
 						    CAIRO_FORMAT_ARGB32,
 						    1, 1, 4);
     assert (cairo_surface_status (surface0) == CAIRO_STATUS_SUCCESS);
-    status = cairo_surface_write_to_png (surface0, "png-test.png");
+    status = cairo_surface_write_to_png (surface0, filename);
     if (status) {
-	cairo_test_log (&ctx, "Error writing 'png-test.png': %s\n",
-			cairo_status_to_string (status));
+	cairo_test_log (ctx, "Error writing '%s': %s\n",
+			filename, cairo_status_to_string (status));
 	result = CAIRO_TEST_FAILURE;
     }
-    surface1 = cairo_image_surface_create_from_png ("png-test.png");
+    surface1 = cairo_image_surface_create_from_png (filename);
     status = cairo_surface_status (surface1);
     if (status) {
-	cairo_test_log (&ctx, "Error reading 'png-test.png': %s\n",
-			cairo_status_to_string (status));
+	cairo_test_log (ctx, "Error reading '%s': %s\n",
+			filename, cairo_status_to_string (status));
 	result = CAIRO_TEST_FAILURE;
     }
 
     if (! image_surface_equals (surface0, surface1)) {
-	cairo_test_log (&ctx, "Error surface mismatch.\n");
-	cairo_test_log (&ctx, "to png: "); print_surface (&ctx, surface0);
-	cairo_test_log (&ctx, "from png: "); print_surface (&ctx, surface1);
+	cairo_test_log (ctx, "Error surface mismatch.\n");
+	cairo_test_log (ctx, "to png: "); print_surface (ctx, surface0);
+	cairo_test_log (ctx, "from png: "); print_surface (ctx, surface1);
 	result = CAIRO_TEST_FAILURE;
     }
     assert (*(uint32_t *) cairo_image_surface_get_data (surface1) == argb32);
@@ -117,24 +114,24 @@ main (void)
 						    CAIRO_FORMAT_RGB24,
 						    1, 1, 4);
     assert (cairo_surface_status (surface0) == CAIRO_STATUS_SUCCESS);
-    status = cairo_surface_write_to_png (surface0, "png-test.png");
+    status = cairo_surface_write_to_png (surface0, filename);
     if (status) {
-	cairo_test_log (&ctx, "Error writing 'png-test.png': %s\n",
-			cairo_status_to_string (status));
+	cairo_test_log (ctx, "Error writing '%s': %s\n",
+			filename, cairo_status_to_string (status));
 	result = CAIRO_TEST_FAILURE;
     }
-    surface1 = cairo_image_surface_create_from_png ("png-test.png");
+    surface1 = cairo_image_surface_create_from_png (filename);
     status = cairo_surface_status (surface1);
     if (status) {
-	cairo_test_log (&ctx, "Error reading 'png-test.png': %s\n",
-			cairo_status_to_string (status));
+	cairo_test_log (ctx, "Error reading '%s': %s\n",
+			filename, cairo_status_to_string (status));
 	result = CAIRO_TEST_FAILURE;
     }
 
     if (! image_surface_equals (surface0, surface1)) {
-	cairo_test_log (&ctx, "Error surface mismatch.\n");
-	cairo_test_log (&ctx, "to png: "); print_surface (&ctx, surface0);
-	cairo_test_log (&ctx, "from png: "); print_surface (&ctx, surface1);
+	cairo_test_log (ctx, "Error surface mismatch.\n");
+	cairo_test_log (ctx, "to png: "); print_surface (ctx, surface0);
+	cairo_test_log (ctx, "from png: "); print_surface (ctx, surface1);
 	result = CAIRO_TEST_FAILURE;
     }
     assert ((*(uint32_t *) cairo_image_surface_get_data (surface1) & RGB_MASK)
@@ -143,7 +140,12 @@ main (void)
     cairo_surface_destroy (surface0);
     cairo_surface_destroy (surface1);
 
-    cairo_test_fini (&ctx);
-
     return result;
 }
+
+CAIRO_TEST (png,
+	    "Check that the png export/import is idempotent.",
+	    "png, api", /* keywords */
+	    NULL, /* requirements */
+	    0, 0,
+	    preamble, NULL)
diff --git a/test/ps-features.c b/test/ps-features.c
index 64b5c60..80088ff 100644
--- a/test/ps-features.c
+++ b/test/ps-features.c
@@ -45,7 +45,7 @@
 
 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof(arr[0]))
 
-struct {
+static struct {
     const char *page_size;
     const char *page_size_alias;
     const char *orientation;
@@ -86,10 +86,9 @@ struct {
      MM_TO_POINTS(37), MM_TO_POINTS(26)}
 };
 
-int
-main (void)
+static cairo_test_status_t
+preamble (cairo_test_context_t *ctx)
 {
-    cairo_test_context_t ctx;
     cairo_surface_t *surface;
     cairo_t *cr;
     cairo_status_t status;
@@ -97,15 +96,13 @@ main (void)
     size_t i;
     char dsc[255];
 
-    cairo_test_init (&ctx, "ps-features");
-    if (! (cairo_test_is_target_enabled (&ctx, "ps2") ||
-	   cairo_test_is_target_enabled (&ctx, "ps3")))
+    if (! (cairo_test_is_target_enabled (ctx, "ps2") ||
+	   cairo_test_is_target_enabled (ctx, "ps3")))
     {
-	cairo_test_fini (&ctx);
 	return CAIRO_TEST_UNTESTED;
     }
 
-    filename = "ps-features.ps";
+    filename = "ps-features-out.ps";
 
     /* We demonstrate that the initial size doesn't matter (we're
      * passing 0,0), if we use cairo_ps_surface_set_size on the first
@@ -126,7 +123,7 @@ main (void)
 			    CAIRO_FONT_WEIGHT_NORMAL);
     cairo_set_font_size (cr, TEXT_SIZE);
 
-    for (i=0; i < ARRAY_SIZE(pages); i++) {
+    for (i = 0; i < ARRAY_SIZE (pages); i++) {
 	cairo_ps_surface_set_size (surface,
 				   pages[i].width_in_points,
 				   pages[i].height_in_points);
@@ -151,14 +148,18 @@ main (void)
     cairo_surface_destroy (surface);
 
     if (status) {
-	cairo_test_log (&ctx, "Failed to create ps surface for file %s: %s\n",
+	cairo_test_log (ctx, "Failed to create ps surface for file %s: %s\n",
 			filename, cairo_status_to_string (status));
 	return CAIRO_TEST_FAILURE;
     }
 
     printf ("ps-features: Please check %s to ensure it looks/prints correctly.\n", filename);
-
-    cairo_test_fini (&ctx);
-
     return CAIRO_TEST_SUCCESS;
 }
+
+CAIRO_TEST (ps_features,
+	    "Check PS specific API",
+	    "ps, api", /* keywords */
+	    NULL, /* requirements */
+	    0, 0,
+	    preamble, NULL)
diff --git a/test/ps-surface-source.c b/test/ps-surface-source.c
index 8f584d6..41016f4 100644
--- a/test/ps-surface-source.c
+++ b/test/ps-surface-source.c
@@ -26,7 +26,6 @@
 #include "cairo-test.h"
 #include <cairo-ps.h>
 
-#define NAME "ps"
 #include "surface-source.c"
 
 static cairo_surface_t *
@@ -34,8 +33,15 @@ create_source_surface (int size)
 {
     cairo_surface_t *surface;
 
-    surface = cairo_ps_surface_create ("ps-surface-source.ps", size, size);
+    surface = cairo_ps_surface_create ("ps-surface-source-out.ps", size, size);
     cairo_surface_set_fallback_resolution (surface, 72., 72.);
 
     return surface;
 }
+
+CAIRO_TEST (ps_surface_source,
+	    "Test using a PS surface as the source",
+	    "source", /* keywords */
+	    NULL, /* requirements */
+	    SIZE, SIZE,
+	    preamble, draw)
diff --git a/test/pthread-show-text.c b/test/pthread-show-text.c
index d612019..d95ce20 100644
--- a/test/pthread-show-text.c
+++ b/test/pthread-show-text.c
@@ -71,31 +71,29 @@ start (void *closure)
     return NULL;
 }
 
-int
-main (int argc, char *argv[])
+static cairo_test_status_t
+preamble (cairo_test_context_t *ctx)
 {
-    cairo_test_context_t ctx;
-    int err;
-    int i, num_threads;
     pthread_t *pthread;
+    int i, num_threads;
+    cairo_test_status_t status = CAIRO_TEST_SUCCESS;
 
-    if (argc > 1) {
-	num_threads = atoi (argv[1]);
-    } else {
+    num_threads = 0;
+    if (getenv ("CAIRO_TEST_NUM_THREADS"))
+	num_threads = atoi (getenv ("CAIRO_TEST_NUM_THREADS"));
+    if (num_threads == 0)
 	num_threads = NUM_THREADS_DEFAULT;
-    }
-
-    cairo_test_init (&ctx, "pthread-show-text");
-    cairo_test_log (&ctx, "Running with %d threads.\n", num_threads);
+    cairo_test_log (ctx, "Running with %d threads.\n", num_threads);
 
     pthread = xmalloc (num_threads * sizeof (pthread_t));
 
     for (i = 0; i < num_threads; i++) {
-	err = pthread_create (&pthread[i], NULL, start, NULL);
+	int err = pthread_create (&pthread[i], NULL, start, NULL);
 	if (err) {
-	    cairo_test_log (&ctx, "pthread_create failed: %s\n", strerror(err));
-	    cairo_test_fini (&ctx);
-	    return CAIRO_TEST_FAILURE;
+	    cairo_test_log (ctx, "pthread_create failed: %s\n", strerror(err));
+	    num_threads = i;
+	    status = CAIRO_TEST_FAILURE;
+	    break;
 	}
     }
 
@@ -104,7 +102,12 @@ main (int argc, char *argv[])
 
     free (pthread);
 
-    cairo_test_fini (&ctx);
-
-    return CAIRO_TEST_SUCCESS;
+    return status;
 }
+
+CAIRO_TEST (pthread_show_text,
+	    "Concurrent stress test of the cairo_show_text().",
+	    "thread, text", /* keywords */
+	    NULL, /* requirements */
+	    0, 0,
+	    preamble, NULL)
diff --git a/test/push-group.c b/test/push-group.c
index c142278..8e6ce19 100644
--- a/test/push-group.c
+++ b/test/push-group.c
@@ -32,15 +32,6 @@
 #define WIDTH (UNIT_SIZE + PAD) + PAD
 #define HEIGHT (UNIT_SIZE + PAD) + PAD
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "push-group",
-    "Verify that cairo_push_group works.",
-    WIDTH, HEIGHT,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -114,8 +105,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (push_group,
+	    "Verify that cairo_push_group works.",
+	    "group", /* keywords */
+	    NULL, /* requirements */
+	    WIDTH, HEIGHT,
+	    NULL, draw)
diff --git a/test/radial-gradient.c b/test/radial-gradient.c
index 7a56ec1..9793fea 100644
--- a/test/radial-gradient.c
+++ b/test/radial-gradient.c
@@ -26,23 +26,14 @@
 
 #include "cairo-test.h"
 
-static cairo_test_draw_function_t draw;
-
 #define NUM_GRADIENTS 4
 #define NUM_EXTEND 4
 #define SIZE 60
 #define WIDTH (SIZE * NUM_GRADIENTS)
 #define HEIGHT (SIZE * NUM_EXTEND)
 
-static const cairo_test_t test = {
-    "radial-gradient",
-    "Simple test of radial gradients",
-    WIDTH, HEIGHT,
-    draw
-};
-
 static void
-draw_gradient (cairo_t 		*cr,
+draw_gradient (cairo_t		*cr,
 	       int		x,
 	       int		y,
 	       int		size,
@@ -103,8 +94,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (radial_gradient,
+	    "Simple test of radial gradients",
+	    "gradient", /* keywords */
+	    NULL, /* requirements */
+	    WIDTH, HEIGHT,
+	    NULL, draw)
diff --git a/test/random-intersections.c b/test/random-intersections.c
index bf3c98c..75e6b62 100644
--- a/test/random-intersections.c
+++ b/test/random-intersections.c
@@ -25,18 +25,11 @@
  */
 #include "cairo-test.h"
 
-static cairo_test_draw_function_t draw;
 #define SIZE 512
 #define NUM_SEGMENTS 128
 
-static const cairo_test_t test = {
-    "random-intersections",
-    "Tests the tessellator trapezoid generation and intersection computation",
-    SIZE+3, SIZE+3,
-    draw
-};
-
 static uint32_t state;
+
 static double
 uniform_random (double minval, double maxval)
 {
@@ -76,8 +69,10 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (random_intersections,
+	    "Tests the tessellator trapezoid generation and intersection computation",
+	    "trap", /* keywords */
+	    NULL, /* requirements */
+	    SIZE+3, SIZE+3,
+	    NULL, draw)
+
diff --git a/test/rectangle-rounding-error.c b/test/rectangle-rounding-error.c
index 5d8fd78..6ad99ae 100644
--- a/test/rectangle-rounding-error.c
+++ b/test/rectangle-rounding-error.c
@@ -30,16 +30,6 @@
  *      https://bugs.freedesktop.org/show_bug.cgi?id=4137
  */
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "rectangle-rounding-error",
-    "This demonstrates (or not) a rounding error that causes a gap between "
-    "two neighbouring rectangles.",
-    76, 76,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -65,8 +55,10 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (rectangle_rounding_error,
+	    "This demonstrates (or not) a rounding error that causes a gap between "
+	    "two neighbouring rectangles.",
+	    "trap", /* keywords */
+	    "target=raster", /* requirements */
+	    76, 76,
+	    NULL, draw)
diff --git a/test/rectilinear-fill.c b/test/rectilinear-fill.c
index 14fc511..3678379 100644
--- a/test/rectilinear-fill.c
+++ b/test/rectilinear-fill.c
@@ -28,15 +28,6 @@
 
 #define SIZE 24
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "rectilinear-fill",
-    "Test rectilinear fill operations (covering only whole pixels)",
-    SIZE, 2 * SIZE,
-    draw
-};
-
 static void
 draw_rectangles (cairo_t *cr)
 {
@@ -85,8 +76,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (rectilinear_fill,
+	    "Test rectilinear fill operations (covering only whole pixels)",
+	    "fill, rectilinear", /* keywords */
+	    NULL, /* requirements */
+	    SIZE, 2 * SIZE,
+	    NULL, draw)
diff --git a/test/rectilinear-miter-limit.c b/test/rectilinear-miter-limit.c
index a935fd5..581d98b 100644
--- a/test/rectilinear-miter-limit.c
+++ b/test/rectilinear-miter-limit.c
@@ -31,15 +31,6 @@
 #define WIDTH	    (PAD + LINE_WIDTH + PAD)
 #define HEIGHT	    (WIDTH)
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "rectilinear-miter-limit",
-    "Test that the rectilinear stroke optimization doesn't break cairo_set_miter_limit",
-    WIDTH, HEIGHT,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -73,8 +64,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (rectilinear_miter_limit,
+	    "Test that the rectilinear stroke optimization doesn't break cairo_set_miter_limit",
+	    "miter, stroke, stress", /* keywords */
+	    NULL, /* requirements */
+	    WIDTH, HEIGHT,
+	    NULL, draw)
diff --git a/test/rectilinear-stroke.c b/test/rectilinear-stroke.c
index 3c67586..e05ff8c 100644
--- a/test/rectilinear-stroke.c
+++ b/test/rectilinear-stroke.c
@@ -28,15 +28,6 @@
 
 #define SIZE 25
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "rectilinear-stroke",
-    "Test rectilinear stroke operations (covering only whole pixels)",
-    SIZE, SIZE,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -139,8 +130,10 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (rectilinear_stroke,
+	    "Test rectilinear stroke operations (covering only whole pixels)",
+	    "stroke", /* keywords */
+	    NULL, /* requirements */
+	    SIZE, SIZE,
+	    NULL, draw)
+
diff --git a/test/reflected-stroke.c b/test/reflected-stroke.c
index 1721009..0981f75 100644
--- a/test/reflected-stroke.c
+++ b/test/reflected-stroke.c
@@ -25,15 +25,6 @@
 
 #include "cairo-test.h"
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "reflected-stroke",
-    "Exercises the stroker with a reflected ctm",
-    200, 200,
-    draw
-};
-
 static void
 draw_symbol (cairo_t *cr)
 {
@@ -92,9 +83,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
-
+CAIRO_TEST (reflected_stroke,
+	    "Exercises the stroker with a reflected ctm",
+	    "stroke, transform", /* keywords */
+	    NULL, /* requirements */
+	    200, 200,
+	    NULL, draw)
diff --git a/test/rel-path.c b/test/rel-path.c
index 38096bc..1544001 100644
--- a/test/rel-path.c
+++ b/test/rel-path.c
@@ -24,15 +24,6 @@
 
 #define SIZE 10
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "rel-path",
-    "Tests calls to various relative path functions",
-    SIZE, SIZE,
-    draw
-};
-
 static cairo_status_t
 invalid_rel_move_to (cairo_surface_t *target)
 {
@@ -117,8 +108,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (rel_path,
+	    "Tests calls to various relative path functions",
+	    "path", /* keywords */
+	    NULL, /* requirements */
+	    SIZE, SIZE,
+	    NULL, draw)
diff --git a/test/rgb24-ignore-alpha.c b/test/rgb24-ignore-alpha.c
index 1d2b167..cd67ed3 100644
--- a/test/rgb24-ignore-alpha.c
+++ b/test/rgb24-ignore-alpha.c
@@ -26,18 +26,9 @@
 
 #include "cairo-test.h"
 
-static cairo_test_draw_function_t draw;
-
 #define WIDTH  2
 #define HEIGHT 2
 
-static const cairo_test_t test = {
-    "rgb24-ignore-alpha",
-    "Test that when using an RGB24 image as a source, there is no alpha channel",
-    WIDTH, HEIGHT,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -60,8 +51,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (rgb24_ignore_alpha,
+	    "Test that when using an RGB24 image as a source, there is no alpha channel",
+	    "image, alpha", /* keywords */
+	    NULL, /* requirements */
+	    WIDTH, HEIGHT,
+	    NULL, draw)
diff --git a/test/rotate-image-surface-paint.c b/test/rotate-image-surface-paint.c
index f1e9e4f..a2db1b0 100644
--- a/test/rotate-image-surface-paint.c
+++ b/test/rotate-image-surface-paint.c
@@ -26,19 +26,9 @@
 
 #include "cairo-test.h"
 
-static cairo_test_draw_function_t draw;
-
 #define SIZE 20
 #define PAD 2
 
-static const cairo_test_t test = {
-    "rotate-image-surface-paint",
-    "Test call sequence: image_surface_create; rotate; set_source_surface; paint"
-    "\nThis test is known to fail on the ps backend currently",
-    SIZE, SIZE,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -92,8 +82,10 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (rotate_image_surface_paint,
+	    "Test call sequence: image_surface_create; rotate; set_source_surface; paint"
+	    "\nThis test is known to fail on the ps backend currently",
+	    "image, transform, paint", /* keywords */
+	    NULL, /* requirements */
+	    SIZE, SIZE,
+	    NULL, draw)
diff --git a/test/scale-down-source-surface-paint.c b/test/scale-down-source-surface-paint.c
index 2a2efcc..293cbda 100644
--- a/test/scale-down-source-surface-paint.c
+++ b/test/scale-down-source-surface-paint.c
@@ -25,15 +25,6 @@
 
 #include "cairo-test.h"
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "scale-down-source-surface-paint",
-    "Test call sequence: cairo_scale; cairo_set_source_surface; cairo_paint, with a scale < 1.0",
-    6, 6,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -65,8 +56,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (scale_down_source_surface_paint,
+	    "Test call sequence: cairo_scale; cairo_set_source_surface; cairo_paint, with a scale < 1.0",
+	    "paint, transform", /* keywords */
+	    NULL, /* requirements */
+	    6, 6,
+	    NULL, draw)
diff --git a/test/scale-source-surface-paint.c b/test/scale-source-surface-paint.c
index 9473342..1e36afd 100644
--- a/test/scale-source-surface-paint.c
+++ b/test/scale-source-surface-paint.c
@@ -25,15 +25,6 @@
 
 #include "cairo-test.h"
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "scale-source-surface-paint",
-    "Test call sequence: cairo_scale; cairo_set_source_surface; cairo_paint",
-    12, 12,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -60,8 +51,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (scale_source_surface_paint,
+	    "Test call sequence: cairo_scale; cairo_set_source_surface; cairo_paint",
+	    "paint, transform", /* keywords */
+	    NULL, /* requirements */
+	    12, 12,
+	    NULL, draw)
diff --git a/test/select-font-face.c b/test/select-font-face.c
index c5ff56b..74c1276 100644
--- a/test/select-font-face.c
+++ b/test/select-font-face.c
@@ -27,32 +27,21 @@
 
 #define TEXT_SIZE 12
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "select-font-face",
-    "Tests using cairo_select_font_face to draw text in different faces",
-    192, TEXT_SIZE + 4,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
     /* We draw in the default black, so paint white first. */
-    cairo_save (cr);
     cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); /* white */
     cairo_paint (cr);
-    cairo_restore (cr);
 
     cairo_set_source_rgb (cr, 0, 0, 0); /* black */
 
+    cairo_set_font_size (cr, TEXT_SIZE);
+    cairo_move_to (cr, 0, TEXT_SIZE);
+
     cairo_select_font_face (cr, "Bitstream Vera Serif",
 			    CAIRO_FONT_SLANT_NORMAL,
 			    CAIRO_FONT_WEIGHT_NORMAL);
-    cairo_set_font_size (cr, TEXT_SIZE);
-
-    cairo_move_to (cr, 0, TEXT_SIZE);
     cairo_show_text (cr, "i-am-serif");
 
     cairo_select_font_face (cr, "Bitstream Vera Sans",
@@ -68,8 +57,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (select_font_face,
+	    "Tests using cairo_select_font_face to draw text in different faces",
+	    "font", /* keywords */
+	    NULL, /* requirements */
+	    192, TEXT_SIZE + 4,
+	    NULL, draw)
diff --git a/test/select-font-no-show-text.c b/test/select-font-no-show-text.c
index 752891b..63b1eb2 100644
--- a/test/select-font-no-show-text.c
+++ b/test/select-font-no-show-text.c
@@ -41,15 +41,6 @@
 #include <math.h>
 #include "cairo-test.h"
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "select-font-no-show-text",
-    "Test calling cairo_select_font_face but never drawing text.",
-    0, 0,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -60,8 +51,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (select_font_no_show_text,
+	    "Test calling cairo_select_font_face but never drawing text.",
+	    "font", /* keywords */
+	    NULL, /* requirements */
+	    0, 0,
+	    NULL, draw)
diff --git a/test/self-copy-overlap.c b/test/self-copy-overlap.c
index 5b1da90..d9e6caa 100644
--- a/test/self-copy-overlap.c
+++ b/test/self-copy-overlap.c
@@ -27,17 +27,7 @@
 
 #include "cairo-test.h"
 
-static cairo_test_draw_function_t draw;
-
 /* This test is only interesting if the target has alpha */
-static const cairo_test_t test = {
-    "self-copy-overlap",
-    "Tests painting to itself using itself as the source"
-    "\nBackends treat this case inconsistently---vector backends are creating snapshots.",
-    200, 200,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -50,8 +40,10 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (self_copy_overlap,
+	    "Tests painting to itself using itself as the source"
+	    "\nBackends treat this case inconsistently---vector backends are creating snapshots.",
+	    "XFAIL=!image,test-meta,test-paginated,pdf,ps,svg self-copy", /* keywords */
+	    NULL, /* requirements */
+	    200, 200,
+	    NULL, draw)
diff --git a/test/self-copy.c b/test/self-copy.c
index 1afb31e..32a375a 100644
--- a/test/self-copy.c
+++ b/test/self-copy.c
@@ -29,15 +29,6 @@
 
 #define SIZE 40
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "self-copy",
-    "Test copying from a surface to itself with a clip",
-    SIZE, SIZE,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -85,8 +76,9 @@ draw (cairo_t *cr, int width, int height)
 
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (self_copy,
+	    "Test copying from a surface to itself with a clip",
+	    "paint", /* keywords */
+	    NULL, /* requirements */
+	    SIZE, SIZE,
+	    NULL, draw)
diff --git a/test/self-intersecting.c b/test/self-intersecting.c
index d2b6265..23a06c7 100644
--- a/test/self-intersecting.c
+++ b/test/self-intersecting.c
@@ -44,16 +44,6 @@
 
 #include "cairo-test.h"
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "self-intersecting",
-    "Test strokes of self-intersecting paths"
-    "\nSelf-intersecting strokes are wrong due to incremental trapezoidization.",
-    10, 20,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -85,8 +75,10 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (self_intersecting,
+	    "Test strokes of self-intersecting paths"
+	    "\nSelf-intersecting strokes are wrong due to incremental trapezoidization.",
+	    "XFAIL stroke, trap", /* keywords */
+	    NULL, /* requirements */
+	    10, 20,
+	    NULL, draw)
diff --git a/test/set-source.c b/test/set-source.c
index 05dd3cb..f326103 100644
--- a/test/set-source.c
+++ b/test/set-source.c
@@ -25,15 +25,6 @@
 
 #include "cairo-test.h"
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "set-source",
-    "Tests calls to various set_source functions",
-    5, 5,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -81,8 +72,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (set_source,
+	    "Tests calls to various set_source functions",
+	    "api", /* keywords */
+	    NULL, /* requirements */
+	    5, 5,
+	    NULL, draw)
diff --git a/test/show-glyphs-many.c b/test/show-glyphs-many.c
index c8d570c..7276b07 100644
--- a/test/show-glyphs-many.c
+++ b/test/show-glyphs-many.c
@@ -79,15 +79,6 @@
 #define TEXT_SIZE 12
 #define NUM_GLYPHS 65535
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "show-glyphs-many",
-    "Test that cairo_show_glyphs works when handed 'many' glyphs",
-    9, 11,
-    draw
-};
-
 static cairo_test_status_t
 get_glyph (cairo_t *cr, const char *utf8, cairo_glyph_t *glyph)
 {
@@ -169,8 +160,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (show_glyphs_many,
+	    "Test that cairo_show_glyphs works when handed 'many' glyphs",
+	    "text, stress", /* keywords */
+	    NULL, /* requirements */
+	    9, 11,
+	    NULL, draw)
diff --git a/test/show-text-current-point.c b/test/show-text-current-point.c
index 2fd2387..acf6d1c 100644
--- a/test/show-text-current-point.c
+++ b/test/show-text-current-point.c
@@ -27,15 +27,6 @@
 
 #define TEXT_SIZE 12
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "show-text-current-point",
-    "Test that cairo_show_text adjusts the current point properly",
-    263, TEXT_SIZE + 4,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -54,14 +45,15 @@ draw (cairo_t *cr, int width, int height)
 
     cairo_move_to (cr, 0, TEXT_SIZE);
     cairo_show_text (cr, "Hello from the ");
-    cairo_show_text (cr, test.name);
+    cairo_show_text (cr, "show-text-current-point");
     cairo_show_text (cr, " test.");
 
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (show_text_current_point,
+	    "Test that cairo_show_text adjusts the current point properly",
+	    "text, api", /* keywords */
+	    NULL, /* requirements */
+	    263, TEXT_SIZE + 4,
+	    NULL, draw)
diff --git a/test/skew-extreme.c b/test/skew-extreme.c
index c682d08..69299a8 100644
--- a/test/skew-extreme.c
+++ b/test/skew-extreme.c
@@ -55,15 +55,6 @@
 #define WIDTH		(PAD + (LINE_LENGTH * SKEW_FACTOR) + LINE_WIDTH + PAD)
 #define HEIGHT		(PAD + LINE_WIDTH + (LINE_LENGTH * SKEW_FACTOR) + LINE_WIDTH + PAD)
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "skew-extreme",
-    "Test cases of extreme skew.",
-    WIDTH, HEIGHT,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -119,8 +110,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (skew_extreme,
+	    "Test cases of extreme skew.",
+	    "transform, stroke", /* keywords */
+	    NULL, /* requirements */
+	    WIDTH, HEIGHT,
+	    NULL, draw)
diff --git a/test/smask-fill.c b/test/smask-fill.c
index 58d32c1..cb38610 100644
--- a/test/smask-fill.c
+++ b/test/smask-fill.c
@@ -25,15 +25,6 @@
 
 #include "cairo-test.h"
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "smask-fill",
-    "Test the support of \"soft\" masks with fills",
-    60, 60,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -74,8 +65,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (smask_fill,
+	    "Test the support of \"soft\" masks with fills",
+	    "smask, fill", /* keywords */
+	    NULL, /* requirements */
+	    60, 60,
+	    NULL, draw)
diff --git a/test/smask-image-mask.c b/test/smask-image-mask.c
index 1f250d1..1418721 100644
--- a/test/smask-image-mask.c
+++ b/test/smask-image-mask.c
@@ -25,15 +25,6 @@
 
 #include "cairo-test.h"
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "smask-image-mask",
-    "Test the support of \"soft\" masks with a secondary image mask",
-    60, 60,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -84,8 +75,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (smask_image_mask,
+	    "Test the support of \"soft\" masks with a secondary image mask",
+	    "smask, image", /* keywords */
+	    NULL, /* requirements */
+	    60, 60,
+	    NULL, draw)
diff --git a/test/smask-mask.c b/test/smask-mask.c
index 721ca48..11cff82 100644
--- a/test/smask-mask.c
+++ b/test/smask-mask.c
@@ -25,15 +25,6 @@
 
 #include "cairo-test.h"
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "smask-mask",
-    "Test the support of \"soft\" masks with a secondary mask",
-    60, 60,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -97,8 +88,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (smask_mask,
+	    "Test the support of \"soft\" masks with a secondary mask",
+	    "smask, mask", /* keywords */
+	    NULL, /* requirements */
+	    60, 60,
+	    NULL, draw)
diff --git a/test/smask-paint.c b/test/smask-paint.c
index 8378964..ee781ca 100644
--- a/test/smask-paint.c
+++ b/test/smask-paint.c
@@ -25,15 +25,6 @@
 
 #include "cairo-test.h"
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "smask-paint",
-    "Test the support of \"soft\" masks with paints",
-    60, 60,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -82,8 +73,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (smask_paint,
+	    "Test the support of \"soft\" masks with paints",
+	    "smask, paint", /* keywords */
+	    NULL, /* requirements */
+	    60, 60,
+	    NULL, draw)
diff --git a/test/smask-stroke.c b/test/smask-stroke.c
index 88fc9f0..2a8e7e8 100644
--- a/test/smask-stroke.c
+++ b/test/smask-stroke.c
@@ -25,15 +25,6 @@
 
 #include "cairo-test.h"
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "smask-stroke",
-    "Test the support of \"soft\" masks with strokes",
-    60, 60,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -74,8 +65,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (smask_stroke,
+	    "Test the support of \"soft\" masks with strokes",
+	    "smask, stroke", /* keywords */
+	    NULL, /* requirements */
+	    60, 60,
+	    NULL, draw)
diff --git a/test/smask-text.c b/test/smask-text.c
index 49eb606..c00aca4 100644
--- a/test/smask-text.c
+++ b/test/smask-text.c
@@ -25,15 +25,6 @@
 
 #include "cairo-test.h"
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "smask-text",
-    "Test the support of \"soft\" masks with text",
-    120, 60,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -84,8 +75,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (smask_text,
+	    "Test the support of \"soft\" masks with text",
+	    "smask, text", /* keywords */
+	    NULL, /* keywords */
+	    120, 60,
+	    NULL, draw)
diff --git a/test/smask.c b/test/smask.c
index d6f5e99..d28caca 100644
--- a/test/smask.c
+++ b/test/smask.c
@@ -25,15 +25,6 @@
 
 #include "cairo-test.h"
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "smask",
-    "Test the support of \"soft\" masks",
-    60, 60,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -122,8 +113,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (smask,
+	    "Test the support of \"soft\" masks",
+	    "smask", /* keywords */
+	    NULL, /* requirements */
+	    60, 60,
+	    NULL, draw)
diff --git a/test/solid-pattern-cache-stress.c b/test/solid-pattern-cache-stress.c
index 42928aa..b695472 100644
--- a/test/solid-pattern-cache-stress.c
+++ b/test/solid-pattern-cache-stress.c
@@ -37,15 +37,6 @@
 #define drand48() (rand () / (double) RAND_MAX)
 #endif
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "solid-pattern-cache-stress",
-    "Stress the solid pattern cache and ensure it behaves",
-    1, 1,
-    draw
-};
-
 static cairo_t *
 _cairo_create_similar (cairo_t *cr, int width, int height)
 {
@@ -170,8 +161,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (solid_pattern_cache_stress,
+	    "Stress the solid pattern cache and ensure it behaves",
+	    "stress", /* keywords */
+	    NULL, /* requirements */
+	    1, 1,
+	    NULL, draw)
diff --git a/test/source-clip-scale.c b/test/source-clip-scale.c
index 6434eb0..375f9be 100644
--- a/test/source-clip-scale.c
+++ b/test/source-clip-scale.c
@@ -29,15 +29,6 @@
 
 #define SIZE 12
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "source-clip-scale",
-    "Test that a source surface is not affected by a clip when scaling",
-    SIZE * 2, SIZE,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -83,8 +74,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (source_clip_scale,
+	    "Test that a source surface is not affected by a clip when scaling",
+	    "clip", /* keywords */
+	    NULL, /* requirements */
+	    SIZE * 2, SIZE,
+	    NULL, draw)
diff --git a/test/source-clip.c b/test/source-clip.c
index 1f51f32..cbb2855 100644
--- a/test/source-clip.c
+++ b/test/source-clip.c
@@ -29,15 +29,6 @@
 
 #define SIZE 12
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "source-clip",
-    "Test that a source surface is not affected by a clip",
-    SIZE, SIZE,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -78,8 +69,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (source_clip,
+	    "Test that a source surface is not affected by a clip",
+	    "clip", /* keywords */
+	    NULL, /* requirements */
+	    SIZE, SIZE,
+	    NULL, draw)
diff --git a/test/source-surface-scale-paint.c b/test/source-surface-scale-paint.c
index 908367c..565a1ff 100644
--- a/test/source-surface-scale-paint.c
+++ b/test/source-surface-scale-paint.c
@@ -25,15 +25,6 @@
 
 #include "cairo-test.h"
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "source-surface-scale-paint",
-    "Test call sequence: cairo_set_source_surface; cairo_scale; cairo_paint",
-    8, 8,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -59,8 +50,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (source_surface_scale_paint,
+	    "Test call sequence: cairo_set_source_surface; cairo_scale; cairo_paint",
+	    "transform, paint", /* keywords */
+	    NULL, /* requirements */
+	    8, 8,
+	    NULL, draw)
diff --git a/test/spline-decomposition.c b/test/spline-decomposition.c
index ca6b007..f01a505 100644
--- a/test/spline-decomposition.c
+++ b/test/spline-decomposition.c
@@ -25,15 +25,6 @@
 
 #include "cairo-test.h"
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "spline-decomposition",
-    "Tests splines with various inflection points",
-    390, 260,
-    draw
-};
-
 typedef struct _point {
     double x,y;
 } point_t;
@@ -409,8 +400,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (spline_decomposition,
+	    "Tests splines with various inflection points",
+	    "stroke, spline", /* keywords */
+	    NULL, /* requirements */
+	    390, 260,
+	    NULL, draw)
diff --git a/test/stroke-ctm-caps.c b/test/stroke-ctm-caps.c
index bfe2bef..1bbee83 100644
--- a/test/stroke-ctm-caps.c
+++ b/test/stroke-ctm-caps.c
@@ -26,8 +26,6 @@
 
 #include "cairo-test.h"
 
-static cairo_test_draw_function_t draw;
-
 #define SIZE 100
 #define PAD 2
 #define WIDTH (PAD + SIZE + PAD)
@@ -41,13 +39,6 @@ static cairo_test_draw_function_t draw;
  * (0.8, 0.8, 0.8, 0.4).
  */
 
-static const cairo_test_t test = {
-    "stroke-ctm-caps",
-    "Test that the stroker correctly passes the device-space vector to the stroker for endcaps",
-    WIDTH, HEIGHT,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -79,8 +70,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (stroke_ctm_caps,
+	    "Test that the stroker correctly passes the device-space vector to the stroker for endcaps",
+	    "stroke, transform", /* keywords */
+	    NULL, /* requirements */
+	    WIDTH, HEIGHT,
+	    NULL, draw)
diff --git a/test/stroke-image.c b/test/stroke-image.c
index 6096590..17e6653 100644
--- a/test/stroke-image.c
+++ b/test/stroke-image.c
@@ -25,20 +25,11 @@
 
 #include "cairo-test.h"
 
-static cairo_test_draw_function_t draw;
-
 #define PAD 10
 #define SIZE 100
 #define IMAGE_SIZE (SIZE-PAD*2)
 #define LINE_WIDTH 10
 
-static const cairo_test_t test = {
-    "stroke-image",
-    "Test stroking with an image source, with a non-identity CTM",
-    SIZE, SIZE,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -74,8 +65,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (stroke_image,
+	    "Test stroking with an image source, with a non-identity CTM",
+	    "stroke, image, transform", /* keywords */
+	    NULL, /* requirements */
+	    SIZE, SIZE,
+	    NULL, draw)
diff --git a/test/surface-finish-twice.c b/test/surface-finish-twice.c
index 149f29c..5154e99 100644
--- a/test/surface-finish-twice.c
+++ b/test/surface-finish-twice.c
@@ -42,15 +42,6 @@
 
 #include "cairo-test.h"
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "surface-finish-twice",
-    "Test to exercise a crash when calling cairo_surface_finish twice on the same surface.",
-    0, 0,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -75,8 +66,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (surface_finish_twice,
+	    "Test to exercise a crash when calling cairo_surface_finish twice on the same surface.",
+	    "api", /* keywords */
+	    NULL, /* requirements */
+	    0, 0,
+	    NULL, draw)
diff --git a/test/surface-pattern-big-scale-down.c b/test/surface-pattern-big-scale-down.c
index 21b8000..15cb3a2 100644
--- a/test/surface-pattern-big-scale-down.c
+++ b/test/surface-pattern-big-scale-down.c
@@ -25,18 +25,9 @@
 
 #include "cairo-test.h"
 
-static cairo_test_draw_function_t draw;
-
 #define SRC_WIDTH 2048
 #define SRC_HEIGHT 32
 
-static const cairo_test_t test = {
-    "surface-pattern-big-scale-down",
-    "Test scaled-down transformed not-repeated surface patterns with large images and offsets",
-    512, 16,
-    draw
-};
-
 static cairo_surface_t *
 create_source_surface (int w, int h)
 {
@@ -126,8 +117,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (surface_pattern_big_scale_down,
+	    "Test scaled-down transformed not-repeated surface patterns with large images and offsets",
+	    "XFAIL transform", /* keywords */
+	    NULL, /* requirements */
+	    512, 16,
+	    NULL, draw)
diff --git a/test/surface-pattern-scale-down-pdf-rgb24-ref.png b/test/surface-pattern-scale-down-pdf-rgb24-ref.png
new file mode 100644
index 0000000..c29d804
Binary files /dev/null and b/test/surface-pattern-scale-down-pdf-rgb24-ref.png differ
diff --git a/test/surface-pattern-scale-down.c b/test/surface-pattern-scale-down.c
index fd62a9c..639019c 100644
--- a/test/surface-pattern-scale-down.c
+++ b/test/surface-pattern-scale-down.c
@@ -30,15 +30,6 @@
 
 #define SIZE 200
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "surface-pattern-scale-down",
-    "Test scaled-down transformed not-repeated surface patterns",
-    SIZE, SIZE,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -88,8 +79,10 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (surface_pattern_scale_down,
+	    "Test scaled-down transformed not-repeated surface patterns"
+	    "\nFails xlib backend (with argb32) with inexplicable alpha in result",
+	    "transform", /* keywords */
+	    NULL, /* requirements */
+	    SIZE, SIZE,
+	    NULL, draw)
diff --git a/test/surface-pattern-scale-up.c b/test/surface-pattern-scale-up.c
index 33f62fc..3217f84 100644
--- a/test/surface-pattern-scale-up.c
+++ b/test/surface-pattern-scale-up.c
@@ -33,15 +33,6 @@
 
 #define SIZE 100
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "surface-pattern-scale-up",
-    "Test scaled-up transformed not-repeated surface patterns",
-    SIZE, SIZE,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -91,8 +82,10 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (surface_pattern_scale_up,
+	    "Test scaled-up transformed not-repeated surface patterns"
+	    "\nFails xlib backend (with argb32) with inexplicable alpha in result",
+	    "transform", /* keywords */
+	    NULL, /* requirements */
+	    SIZE, SIZE,
+	    NULL, draw)
diff --git a/test/surface-pattern.c b/test/surface-pattern.c
index 7739cae..ff95475 100644
--- a/test/surface-pattern.c
+++ b/test/surface-pattern.c
@@ -29,19 +29,9 @@
 #include <stdio.h>
 
 #define SIZE 140
-
-/* Not GhostScript does not support /Interpolate on rotated images, so the PS
+/* Note GhostScript does not support /Interpolate on rotated images, so the PS
  * output looks terrible, but is a known issue. */
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "surface-pattern",
-    "Test transformed repeated surface patterns",
-    SIZE, SIZE,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -91,8 +81,10 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (surface_pattern,
+	    "Test transformed repeated surface patterns"
+	    "\nExhibiting a strange (very minor) failure in ps backend with device-offset",
+	    "transform", /* keywords */
+	    NULL, /* requirements */
+	    SIZE, SIZE,
+	    NULL, draw)
diff --git a/test/surface-source.c b/test/surface-source.c
index 63b77a7..0906924 100644
--- a/test/surface-source.c
+++ b/test/surface-source.c
@@ -25,7 +25,6 @@
 
 #include "cairo-test.h"
 
-static cairo_test_draw_function_t draw;
 static cairo_surface_t *create_source_surface (int size);
 
 /* We use a relatively large source to exercise bug:
@@ -35,13 +34,7 @@ static cairo_surface_t *create_source_surface (int size);
  */
 #define SOURCE_SIZE 2000
 #define INTER_SIZE 512
-
-static const cairo_test_t test = {
-    NAME "-surface-source",
-    "Test using various surfaces as the source",
-    90, 90,
-    draw
-};
+#define SIZE 90
 
 static void
 draw_pattern (cairo_surface_t **surface_inout, int surface_size)
@@ -117,8 +110,8 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
+static cairo_test_status_t
+preamble (cairo_test_context_t *ctx)
 {
     cairo_surface_t *surface;
 
@@ -128,5 +121,5 @@ main (void)
 
     cairo_surface_destroy (surface);
 
-    return cairo_test (&test);
+    return CAIRO_TEST_SUCCESS;
 }
diff --git a/test/svg-clip.c b/test/svg-clip.c
index 255b71f..4a6cf07 100644
--- a/test/svg-clip.c
+++ b/test/svg-clip.c
@@ -103,29 +103,25 @@ test_clip (cairo_t *cr, double width, double height)
     cairo_fill (cr);
 }
 
-int
-main (void)
+static cairo_test_status_t
+preamble (cairo_test_context_t *ctx)
 {
-    cairo_test_context_t ctx;
     cairo_t *cr;
-    const char *filename = "svg-clip.svg";
+    const char *filename = "svg-clip-out.svg";
     cairo_surface_t *surface;
 
-    cairo_test_init (&ctx, "svg-clip");
-    if (! (cairo_test_is_target_enabled (&ctx, "svg11") ||
-	   cairo_test_is_target_enabled (&ctx, "svg12")))
+    if (! cairo_test_is_target_enabled (ctx, "svg11") &&
+	! cairo_test_is_target_enabled (ctx, "svg12"))
     {
-	cairo_test_fini (&ctx);
 	return CAIRO_TEST_UNTESTED;
     }
 
     surface = cairo_svg_surface_create (filename,
 					WIDTH_IN_POINTS, HEIGHT_IN_POINTS);
     if (cairo_surface_status (surface)) {
-	cairo_test_log (&ctx,
+	cairo_test_log (ctx,
 			"Failed to create svg surface for file %s: %s\n",
 			filename, cairo_status_to_string (cairo_surface_status (surface)));
-	cairo_test_fini (&ctx);
 	return CAIRO_TEST_FAILURE;
     }
 
@@ -139,8 +135,12 @@ main (void)
 
     printf ("svg-clip: Please check %s to make sure it looks happy.\n",
 	    filename);
-
-    cairo_test_fini (&ctx);
-
     return CAIRO_TEST_SUCCESS;
 }
+
+CAIRO_TEST (svg_clip,
+	    "Test SVG clipping",
+	    "svg, clip", /* keywords */
+	    NULL, /* requirements */
+	    0, 0,
+	    preamble, NULL)
diff --git a/test/svg-surface-source.c b/test/svg-surface-source.c
index c8042c4..d7749e5 100644
--- a/test/svg-surface-source.c
+++ b/test/svg-surface-source.c
@@ -26,7 +26,6 @@
 #include "cairo-test.h"
 #include <cairo-svg.h>
 
-#define NAME "svg"
 #include "surface-source.c"
 
 static cairo_surface_t *
@@ -34,8 +33,16 @@ create_source_surface (int size)
 {
     cairo_surface_t *surface;
 
-    surface = cairo_svg_surface_create ("svg-surface-source.svg", size, size);
+    surface = cairo_svg_surface_create ("svg-surface-source-out.svg",
+					size, size);
     cairo_surface_set_fallback_resolution (surface, 72., 72.);
 
     return surface;
 }
+
+CAIRO_TEST (svg_surface_source,
+	    "Test using a SVG surface as the source",
+	    "source", /* keywords */
+	    NULL, /* requirements */
+	    SIZE, SIZE,
+	    preamble, draw)
diff --git a/test/svg-surface.c b/test/svg-surface.c
index c4eadc9..6f071ce 100644
--- a/test/svg-surface.c
+++ b/test/svg-surface.c
@@ -86,30 +86,26 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
+static cairo_test_status_t
+preamble (cairo_test_context_t *ctx)
 {
-    cairo_test_context_t ctx;
     cairo_t *cr;
-    const char *filename = "svg-surface.svg";
+    const char *filename = "svg-surface-out.svg";
     cairo_surface_t *surface;
 
-    cairo_test_init (&ctx, "svg-surface");
-    if (! (cairo_test_is_target_enabled (&ctx, "svg11") ||
-	   cairo_test_is_target_enabled (&ctx, "svg12")))
+    if (! cairo_test_is_target_enabled (ctx, "svg11") &&
+	! cairo_test_is_target_enabled (ctx, "svg12"))
     {
-	cairo_test_fini (&ctx);
 	return CAIRO_TEST_UNTESTED;
     }
 
     surface = cairo_svg_surface_create (filename,
 					WIDTH_IN_POINTS, HEIGHT_IN_POINTS);
     if (cairo_surface_status (surface)) {
-	cairo_test_log (&ctx,
+	cairo_test_log (ctx,
 			"Failed to create svg surface for file %s: %s\n",
 			filename,
 			cairo_status_to_string (cairo_surface_status (surface)));
-	cairo_test_fini (&ctx);
 	return CAIRO_TEST_FAILURE;
     }
 
@@ -123,8 +119,12 @@ main (void)
     cairo_surface_destroy (surface);
 
     printf ("svg-surface: Please check svg-surface.svg to make sure it looks happy.\n");
-
-    cairo_test_fini (&ctx);
-
     return CAIRO_TEST_SUCCESS;
 }
+
+CAIRO_TEST (svg_surface,
+	    "Check creation of a SVG surface",
+	    "svg", /* keywords */
+	    NULL, /* requirements */
+	    0, 0,
+	    preamble, NULL)
diff --git a/test/text-antialias-gray.c b/test/text-antialias-gray.c
index 2029224..cdc0e06 100644
--- a/test/text-antialias-gray.c
+++ b/test/text-antialias-gray.c
@@ -29,15 +29,6 @@
 #define HEIGHT 22
 #define TEXT_SIZE 12
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "text-antialias-gray",
-    "Tests text rendering with grayscale antialiasing",
-    WIDTH, HEIGHT,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -77,8 +68,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (text_antialias_gray,
+	    "Tests text rendering with grayscale antialiasing",
+	    "text", /* keywords */
+	    "target=raster", /* requirements */
+	    WIDTH, HEIGHT,
+	    NULL, draw)
diff --git a/test/text-antialias-none.c b/test/text-antialias-none.c
index af279d8..cd43f2a 100644
--- a/test/text-antialias-none.c
+++ b/test/text-antialias-none.c
@@ -29,15 +29,6 @@
 #define HEIGHT 22
 #define TEXT_SIZE 12
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "text-antialias-none",
-    "Tests text rendering with no antialiasing",
-    WIDTH, HEIGHT,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -77,8 +68,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (text_antialias_none,
+	    "Tests text rendering with no antialiasing",
+	    "text", /* keywords */
+	    "target=raster", /* requirements */
+	    WIDTH, HEIGHT,
+	    NULL, draw)
diff --git a/test/text-antialias-subpixel.c b/test/text-antialias-subpixel.c
index a92d64f..1a528d6 100644
--- a/test/text-antialias-subpixel.c
+++ b/test/text-antialias-subpixel.c
@@ -29,15 +29,6 @@
 #define HEIGHT 22
 #define TEXT_SIZE 12
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "text-antialias-subpixel",
-    "Tests text rendering with subpixel antialiasing",
-    WIDTH, HEIGHT,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -75,8 +66,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (text_antialias_subpixel,
+	    "Tests text rendering with subpixel antialiasing",
+	    "text", /* keywords */
+	    "target=raster", /* requirements */
+	    WIDTH, HEIGHT,
+	    NULL, draw)
diff --git a/test/text-cache-crash.c b/test/text-cache-crash.c
index b78b3a3..4786af4 100644
--- a/test/text-cache-crash.c
+++ b/test/text-cache-crash.c
@@ -62,16 +62,6 @@
 
 #include "cairo-test.h"
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "text-cache-crash",
-    "Test case for bug causing an assertion failure in _cairo_cache_lookup",
-    0, 0,
-    draw
-};
-#include <cairo.h>
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -89,33 +79,15 @@ draw (cairo_t *cr, int width, int height)
     /* Then there was a bug that choked when selecting a font too big
      * for the cache. */
 
-/* XXX: Sometimes this leads to an assertion:
-
-_cairo_cache_lookup: Assertion `cache->max_memory >= (cache->used_memory + new_entry->memory)' failed.
-Aborted
-
-   But other times my machine hangs completely only to return to life
-   several minutes later with some programs missing. This seems like
-   the out-of-memory killer to me.
-
-   It seems like I usually get the assertion when I run
-   ./text_cache_crash directly and I usually get the machine hang when
-   I run "make check" but I don't know if there's a perfect
-   correlation there.
-
-   So there's a bad bug here somewhere that really needs to be fixed.
-   But in the meantime, I need "make check" not to destory work, so
-   I'm commenting this test out for now.
-
     cairo_set_font_size (cr, 500);
     cairo_show_text (cr, "hello");
-*/
 
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (text_cache_crash,
+	    "Test case for bug causing an assertion failure in _cairo_cache_lookup",
+	    "text, stress", /* keywords */
+	    NULL, /* requirements */
+	    0, 0,
+	    NULL, draw)
diff --git a/test/text-glyph-range-ps2-ref.png b/test/text-glyph-range-ps2-ref.png
new file mode 100644
index 0000000..b20e6bd
Binary files /dev/null and b/test/text-glyph-range-ps2-ref.png differ
diff --git a/test/text-glyph-range-ps3-ref.png b/test/text-glyph-range-ps3-ref.png
new file mode 100644
index 0000000..b20e6bd
Binary files /dev/null and b/test/text-glyph-range-ps3-ref.png differ
diff --git a/test/text-glyph-range-ref.png b/test/text-glyph-range-ref.png
index 086aa4a..a39e46c 100644
Binary files a/test/text-glyph-range-ref.png and b/test/text-glyph-range-ref.png differ
diff --git a/test/text-glyph-range-rgb24-ref.png b/test/text-glyph-range-rgb24-ref.png
deleted file mode 100644
index 9e8232c..0000000
Binary files a/test/text-glyph-range-rgb24-ref.png and /dev/null differ
diff --git a/test/text-glyph-range.c b/test/text-glyph-range.c
index 2af48a2..f6422fe 100644
--- a/test/text-glyph-range.c
+++ b/test/text-glyph-range.c
@@ -26,14 +26,15 @@
  */
 
 /* Related to bug 9530
- * 
+ *
  * cairo_glyph_t can contain any unsigned long in its 'index', the intention
  * being that it is large enough to hold a pointer. However, this means that
  * it can specify many glyph indexes which don't exist in the font, and may
- * exceed the range of legal glyph indexes for the font backend. It may 
- * also contain special values that are not usable as indexes - e.g. 0xffff is 
+ * exceed the range of legal glyph indexes for the font backend. It may
+ * also contain special values that are not usable as indexes - e.g. 0xffff is
  * kATSDeletedGlyphcode in ATSUI, a glyph that should not be drawn.
- * The font backends should handle all legal and out-of-range values consistently.
+ * The font backends should handle all legal and out-of-range values
+ * consistently.
  *
  * This test expects that operations on out-of-range and missing glyphs should
  * act as if they were zero-width.
@@ -46,16 +47,6 @@
 #define NUM_TEXT 20
 #define TEXT_SIZE 12
 
-static cairo_test_draw_function_t draw;
-
-cairo_test_t test = {
-    "text-glyph-range",
-    "Tests show_glyphs, glyph_path, glyph_extents with out of range glyph ids."
-    "\nft and atsui font backends fail, misreporting errors from FT_Load_Glyph and ATSUGlyphGetCubicPaths",
-    WIDTH, HEIGHT,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -71,50 +62,49 @@ draw (cairo_t *cr, int width, int height)
 	-1L, /* out of range */
 	70, 68, 76, 85, 82 /* 'cairo' */
     };
-    
+
     /* We draw in the default black, so paint white first. */
     cairo_save (cr);
     cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); /* white */
     cairo_paint (cr);
     cairo_restore (cr);
-    
+
     cairo_select_font_face (cr, "Bitstream Vera Sans",
 			    CAIRO_FONT_SLANT_NORMAL,
 			    CAIRO_FONT_WEIGHT_NORMAL);
     cairo_set_font_size (cr, 16);
-    
-    
+
     for (i = 0; i < 9; i++) {
 	/* since we're just drawing glyphs directly we need to position them. */
 	cairo_glyph_t glyph = {
 	    index[i], 10 * i, 25
 	};
-	
+
 	/* test cairo_glyph_extents. Every glyph index should
 	 * have extents, invalid glyphs should be zero-width.
 	 */
 	cairo_move_to (cr, glyph.x, glyph.y);
 	cairo_set_line_width (cr, 1.0);
-	cairo_glyph_extents (cr, &glyph, 1, &extents);	
-	cairo_rectangle (cr, 
-			 glyph.x + extents.x_bearing - 0.5, 
-			 glyph.y + extents.y_bearing - 0.5, 
-			 extents.width + 1, 
+	cairo_glyph_extents (cr, &glyph, 1, &extents);
+	cairo_rectangle (cr,
+			 glyph.x + extents.x_bearing - 0.5,
+			 glyph.y + extents.y_bearing - 0.5,
+			 extents.width + 1,
 			 extents.height + 1);
 	cairo_set_source_rgb (cr, 1, 0, 0); /* red */
 	cairo_stroke (cr);
-	
+
 	/* test cairo_show_glyphs. Every glyph index should be
 	 * drawable, invalid glyph indexes should draw nothing.
 	 */
-	cairo_set_source_rgb (cr, 0, 0, 0); /* black */  
+	cairo_set_source_rgb (cr, 0, 0, 0); /* black */
 	cairo_show_glyphs (cr, &glyph, 1);
 	cairo_move_to (cr, glyph.x, glyph.y);
-	
-	/* test cairo_glyph_path. Every glyph index should produce 
+
+	/* test cairo_glyph_path. Every glyph index should produce
 	 * a path, invalid glyph indexes should have empty paths.
 	 */
-	/* Change the glyph position 
+	/* Change the glyph position
 	 * so that the paths are visible.
 	 */
 	glyph.y = 55;
@@ -122,12 +112,14 @@ draw (cairo_t *cr, int width, int height)
 	cairo_glyph_path (cr, &glyph, 1);
 	cairo_fill (cr);
     }
-    
+
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (text_glyph_range,
+	    "Tests show_glyphs, glyph_path, glyph_extents with out of range glyph ids."
+	    "\nft and atsui font backends fail, misreporting errors from FT_Load_Glyph and ATSUGlyphGetCubicPaths",
+	    "text, stress", /* keywords */
+	    NULL, /* requirements */
+	    WIDTH, HEIGHT,
+	    NULL, draw)
diff --git a/test/text-pattern.c b/test/text-pattern.c
index eae9cae..ad4419d 100644
--- a/test/text-pattern.c
+++ b/test/text-pattern.c
@@ -28,46 +28,38 @@
 #define IMAGE_WIDTH 64
 #define IMAGE_HEIGHT 64
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "text-pattern",
-    "Patterned Text\n",
-    IMAGE_WIDTH, IMAGE_HEIGHT,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
-  cairo_pattern_t *pat;
+    cairo_pattern_t *pat;
 
-  cairo_select_font_face (cr, "Bitstream Vera Sans",
-			  CAIRO_FONT_SLANT_NORMAL,
-			  CAIRO_FONT_WEIGHT_NORMAL);
+    cairo_select_font_face (cr, "Bitstream Vera Sans",
+			    CAIRO_FONT_SLANT_NORMAL,
+			    CAIRO_FONT_WEIGHT_NORMAL);
 
-  cairo_scale (cr, width, height);
+    cairo_scale (cr, width, height);
 
-  pat = cairo_pattern_create_linear (0.0, 0.0, 1, 1);
-  cairo_pattern_add_color_stop_rgba (pat, 1, 1, 0, 0, 1);
-  cairo_pattern_add_color_stop_rgba (pat, 0, 0, 0, 1, 1);
-  cairo_set_source (cr, pat);
+    pat = cairo_pattern_create_linear (0.0, 0.0, 1, 1);
+    cairo_pattern_add_color_stop_rgba (pat, 1, 1, 0, 0, 1);
+    cairo_pattern_add_color_stop_rgba (pat, 0, 0, 0, 1, 1);
+    cairo_set_source (cr, pat);
 
-  /* test rectangle - make sure the gradient is set correctly */
-  cairo_rectangle (cr, 0, 0, 0.1, 1);
-  cairo_fill (cr);
+    /* test rectangle - make sure the gradient is set correctly */
+    cairo_rectangle (cr, 0, 0, 0.1, 1);
+    cairo_fill (cr);
 
-  cairo_set_font_size (cr, 0.4);
-  cairo_move_to (cr, 0.1, 0.6);
-  cairo_show_text (cr, "cairo");
+    cairo_set_font_size (cr, 0.4);
+    cairo_move_to (cr, 0.1, 0.6);
+    cairo_show_text (cr, "cairo");
 
-  cairo_pattern_destroy (pat);
+    cairo_pattern_destroy (pat);
 
-  return CAIRO_TEST_SUCCESS;
+    return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (text_pattern,
+	    "Patterned Text",
+	    "text, pattern", /* keywords */
+	    NULL, /* requirements */
+	    IMAGE_WIDTH, IMAGE_HEIGHT,
+	    NULL, draw)
diff --git a/test/text-rotate.c b/test/text-rotate.c
index da21461..2613c88 100644
--- a/test/text-rotate.c
+++ b/test/text-rotate.c
@@ -78,7 +78,7 @@
  *
  * 2007-02-21
  *
- *   Seems like all the "bugs" have been fixed and all remainint is
+ *   Seems like all the "bugs" have been fixed and all remaining is
  *   missing support for subpixel glyph positioning.  Removing from
  *   XFAIL now.
  */
@@ -90,15 +90,6 @@
 #define NUM_TEXT 20
 #define TEXT_SIZE 12
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "text-rotate",
-    "Tests show_text under various rotations",
-    WIDTH, HEIGHT,
-    draw
-};
-
 /* Draw the word cairo at NUM_TEXT different angles */
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
@@ -160,8 +151,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (text_rotate,
+	    "Tests show_text under various rotations",
+	    "text, transform", /* keywords */
+	    NULL, /* requirements */
+	    WIDTH, HEIGHT,
+	    NULL, draw)
diff --git a/test/text-transform.c b/test/text-transform.c
index c1148e5..e5c0e35 100644
--- a/test/text-transform.c
+++ b/test/text-transform.c
@@ -25,21 +25,12 @@
 
 #include "cairo-test.h"
 
-static cairo_test_draw_function_t draw;
-
 #define SIZE 100
 #define PAD 5
 
 #define FONT_SIZE 32.0
 
-static const char png_filename[] = "romedalen.png";
-
-static const cairo_test_t test = {
-    "text-transform",
-    "Test various applications of the font matrix",
-    SIZE, SIZE,
-    draw
-};
+static const char *png_filename = "romedalen.png";
 
 static void
 draw_text (cairo_t *cr)
@@ -105,8 +96,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (text_transform,
+	    "Test various applications of the font matrix",
+	    "text, transform", /* keywords */
+	    NULL, /* requirements */
+	    SIZE, SIZE,
+	    NULL, draw)
diff --git a/test/text-zero-len.c b/test/text-zero-len.c
index dbcd2c5..3efb3ef 100644
--- a/test/text-zero-len.c
+++ b/test/text-zero-len.c
@@ -43,15 +43,6 @@
 #define NUM_TEXT 20
 #define TEXT_SIZE 12
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "text-zero-len",
-    "Tests show_text and text_path with a zero-sized string",
-    0, 0,
-    draw
-};
-
 static cairo_bool_t
 text_extents_equal (const cairo_text_extents_t *A,
 	            const cairo_text_extents_t *B)
@@ -204,8 +195,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (text_zero_len,
+	    "Tests show_text and text_path with a zero-sized string",
+	    "text, stress, extents", /* keywords */
+	    NULL, /* requirements */
+	    0, 0,
+	    NULL, draw)
diff --git a/test/toy-font-face.c b/test/toy-font-face.c
index 7b984eb..e26a19c 100644
--- a/test/toy-font-face.c
+++ b/test/toy-font-face.c
@@ -34,16 +34,13 @@
 #include <assert.h>
 #include <string.h>
 
-int
-main (void)
+static cairo_test_status_t
+preamble (cairo_test_context_t *ctx)
 {
-    cairo_test_context_t ctx;
     cairo_t *cr;
     cairo_surface_t *surface;
     cairo_font_face_t *font_face;
 
-    cairo_test_init (&ctx, "toy-font-face");
-
     surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, 0, 0);
     cr = cairo_create (surface);
     cairo_surface_destroy (surface);
@@ -120,7 +117,12 @@ main (void)
 
     cairo_destroy (cr);
 
-    cairo_test_fini (&ctx);
-
     return CAIRO_TEST_SUCCESS;
 }
+
+CAIRO_TEST (toy_font_face,
+	    "Check the construction of 'toy' font faces",
+	    "font, api", /* keywords */
+	    NULL, /* requirements */
+	    0, 0,
+	    preamble, NULL)
diff --git a/test/transforms.c b/test/transforms.c
index 5731b8e..17b1396 100644
--- a/test/transforms.c
+++ b/test/transforms.c
@@ -28,15 +28,6 @@
 #define WIDTH 45
 #define HEIGHT 30
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "transforms",
-    "Test various transformations.",
-    WIDTH, HEIGHT,
-    draw
-};
-
 static void
 draw_L_shape (cairo_t *cr)
 {
@@ -113,8 +104,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (transforms,
+	    "Test various transformations.",
+	    "transforms, api", /* keywords */
+	    NULL, /* requirements */
+	    WIDTH, HEIGHT,
+	    NULL, draw)
diff --git a/test/translate-show-surface.c b/test/translate-show-surface.c
index 819ab69..bf084fe 100644
--- a/test/translate-show-surface.c
+++ b/test/translate-show-surface.c
@@ -43,15 +43,6 @@
 
 #include "cairo-test.h"
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "translate-show-surface",
-    "Tests calls to cairo_show_surface after cairo_translate",
-    2, 2,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -79,8 +70,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (translate_show_surface,
+	    "Tests calls to cairo_show_surface after cairo_translate",
+	    "transform", /* keywords */
+	    NULL, /* requirements */
+	    2, 2,
+	    NULL, draw)
diff --git a/test/trap-clip.c b/test/trap-clip.c
index 0decb7b..3a8d5c0 100644
--- a/test/trap-clip.c
+++ b/test/trap-clip.c
@@ -31,7 +31,7 @@
 #define HEIGHT 16
 #define PAD 2
 
-static const char	png_filename[]	= "romedalen.png";
+static const char *png_filename = "romedalen.png";
 
 static void
 set_solid_pattern (const cairo_test_context_t *ctx, cairo_t *cr, int x, int y)
@@ -164,15 +164,6 @@ static void (* const clip_funcs[])(cairo_t *cr, int x, int y) = {
 #define IMAGE_WIDTH (ARRAY_SIZE (pattern_funcs) * (WIDTH + PAD) + PAD)
 #define IMAGE_HEIGHT (ARRAY_SIZE (draw_funcs) * ARRAY_SIZE (clip_funcs) * (HEIGHT + PAD) + PAD)
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "trap-clip",
-    "Trapezoid clipping\n",
-    IMAGE_WIDTH, IMAGE_HEIGHT,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -205,8 +196,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (trap_clip,
+	    "Trapezoid clipping",
+	    "clip, trap", /* keywords */
+	    NULL, /* requirements */
+	    IMAGE_WIDTH, IMAGE_HEIGHT,
+	    NULL, draw)
diff --git a/test/truetype-tables.c b/test/truetype-tables.c
index 718af3a..bab119f 100644
--- a/test/truetype-tables.c
+++ b/test/truetype-tables.c
@@ -31,18 +31,14 @@
 
 #include <cairo-truetype-subset-private.h>
 
-int
-main (void)
+static cairo_test_status_t
+preamble (cairo_test_context_t *ctx)
 {
-    cairo_test_context_t ctx;
     cairo_test_status_t ret = CAIRO_TEST_SUCCESS;
 
-    cairo_test_init (&ctx, "truetype-tables");
-    cairo_test_log (&ctx, "Test that the size of TrueType table structs is correct\n");
-
 #define check(st, sz) \
 	if (sizeof (st) != (sz)) { \
-	    cairo_test_log (&ctx, "sizeof (%s): got %d, expected %d", #st, (int)sizeof (st), sz); \
+	    cairo_test_log (ctx, "sizeof (%s): got %d, expected %d", #st, (int)sizeof (st), sz); \
 	    ret = CAIRO_TEST_FAILURE; \
 	}
 #if CAIRO_HAS_FONT_SUBSET
@@ -55,7 +51,13 @@ main (void)
     check (tt_composite_glyph_t,	18);
     check (tt_glyph_data_t,	28);
 #endif
-    cairo_test_fini (&ctx);
 
     return ret;
 }
+
+CAIRO_TEST (truetype_tables,
+	    "Test that the size of TrueType table structs is correct",
+	    "ft, api", /* keywords */
+	    NULL, /* requirements */
+	    0, 0,
+	    preamble, NULL)
diff --git a/test/twin.c b/test/twin.c
index ec004db..34851f4 100644
--- a/test/twin.c
+++ b/test/twin.c
@@ -25,15 +25,6 @@
 
 #include "cairo-test.h"
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "twin",
-    "Tests the internal font",
-    128, 20,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -53,8 +44,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (twin,
+	    "Tests the internal font",
+	    "twin, font", /* keywords */
+	    NULL, /* requirements */
+	    128, 20,
+	    NULL, draw)
diff --git a/test/unantialiased-shapes.c b/test/unantialiased-shapes.c
index 298f1c1..b53ed0d 100644
--- a/test/unantialiased-shapes.c
+++ b/test/unantialiased-shapes.c
@@ -25,15 +25,6 @@
 
 #include "cairo-test.h"
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "unantialiased-shapes",
-    "Test shape drawing without antialiasing",
-    320, 240,
-    draw
-};
-
 /* The star shape from the SVG test suite, from the fill rule test */
 static void
 big_star_path (cairo_t *cr)
@@ -99,8 +90,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (unantialiased_shapes,
+	    "Test shape drawing without antialiasing",
+	    "fill, stroke", /* keywords */
+	    "target=raster", /* requirements */
+	    320, 240,
+	    NULL, draw)
diff --git a/test/unbounded-operator.c b/test/unbounded-operator.c
index 25d4345..f5e1faa 100644
--- a/test/unbounded-operator.c
+++ b/test/unbounded-operator.c
@@ -130,15 +130,6 @@ static cairo_operator_t operators[] = {
 #define IMAGE_WIDTH (ARRAY_SIZE (operators) * (WIDTH + PAD) + PAD)
 #define IMAGE_HEIGHT (ARRAY_SIZE (draw_funcs) * (HEIGHT + PAD) + PAD)
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "unbounded-operator",
-    "Operators with an effect for transparent source/mask",
-    IMAGE_WIDTH, IMAGE_HEIGHT,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -187,8 +178,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (unbounded_operator,
+	    "Operators with an effect for transparent source/mask",
+	    "XFAIL=svg12 operator", /* keywords */
+	    NULL, /* requirements */
+	    IMAGE_WIDTH, IMAGE_HEIGHT,
+	    NULL, draw)
diff --git a/test/user-data.c b/test/user-data.c
index c4e630c..f0e62d1 100644
--- a/test/user-data.c
+++ b/test/user-data.c
@@ -25,7 +25,6 @@
 
 #include "cairo-test.h"
 
-#include <cairo.h>
 #include <assert.h>
 
 static void
@@ -40,16 +39,13 @@ destroy_data2 (void *p)
     *(int *) p = 2;
 }
 
-int
-main (void)
+static cairo_test_status_t
+preamble (cairo_test_context_t *ctx)
 {
-    cairo_test_context_t ctx;
     cairo_surface_t *surface;
     static const cairo_user_data_key_t key1, key2;
     int data1, data2;
 
-    cairo_test_init (&ctx, "user-data");
-
     data1 = 0;
     data2 = 0;
     surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, 1, 1);
@@ -82,7 +78,12 @@ main (void)
     assert (data1 == 1);
     assert (data2 == 2);
 
-    cairo_test_fini (&ctx);
-
     return CAIRO_TEST_SUCCESS;
 }
+
+CAIRO_TEST (user_data,
+	    "Test setting and getting random bits of user data.",
+	    "api", /* keywords */
+	    NULL, /* requirements */
+	    0, 0,
+	    preamble, NULL)
diff --git a/test/user-font-mask.c b/test/user-font-mask.c
index 33f9249..16bd59b 100644
--- a/test/user-font-mask.c
+++ b/test/user-font-mask.c
@@ -39,19 +39,6 @@
 #define HEIGHT ((TEXT_SIZE + 2*BORDER)*2)
 #define TEXT   "cairo"
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "user-font-mask",
-    "Tests a user-font using cairo_mask with bitmap images",
-#ifndef ROTATED
-    WIDTH, HEIGHT,
-#else
-    WIDTH, WIDTH,
-#endif
-    draw
-};
-
 /* Reverse the bits in a byte with 7 operations (no 64-bit):
  * Devised by Sean Anderson, July 13, 2001.
  * Source: http://graphics.stanford.edu/~seander/bithacks.html#ReverseByteWith32Bits
@@ -247,8 +234,13 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (user_font_mask,
+	    "Tests a user-font using cairo_mask with bitmap images",
+	    "user-font, mask", /* keywords */
+	    NULL, /* requirements */
+#ifndef ROTATED
+	    WIDTH, HEIGHT,
+#else
+	    WIDTH, WIDTH,
+#endif
+	    NULL, draw)
diff --git a/test/user-font-proxy.c b/test/user-font-proxy.c
index f3e1f0e..45974d3 100644
--- a/test/user-font-proxy.c
+++ b/test/user-font-proxy.c
@@ -38,19 +38,6 @@
 #define HEIGHT ((TEXT_SIZE + 2*BORDER)*2)
 #define TEXT   "geez... cairo user-font"
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "user-font-proxy",
-    "Tests a user-font using a native font in its render_glyph",
-#ifndef ROTATED
-    WIDTH, HEIGHT,
-#else
-    WIDTH, WIDTH,
-#endif
-    draw
-};
-
 static cairo_user_data_key_t fallback_font_key;
 
 static cairo_status_t
@@ -217,8 +204,13 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (user_font_proxy,
+	    "Tests a user-font using a native font in its render_glyph",
+	    "font, user-font", /* keywords */
+	    "cairo >= 1.7.4", /* requirements */
+#ifndef ROTATED
+	    WIDTH, HEIGHT,
+#else
+	    WIDTH, WIDTH,
+#endif
+	    NULL, draw)
diff --git a/test/user-font-rescale.c b/test/user-font-rescale.c
index bcee414..0c32419 100644
--- a/test/user-font-rescale.c
+++ b/test/user-font-rescale.c
@@ -36,15 +36,6 @@
 #define HEIGHT ((TEXT_SIZE + 2*BORDER)*3 + BORDER)
 #define TEXT   "test of rescaled glyphs"
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "user-font-rescale",
-    "Tests drawing text with user defined widths",
-    WIDTH, HEIGHT,
-    draw
-};
-
 static const cairo_user_data_key_t rescale_font_closure_key;
 
 struct rescaled_font {
@@ -364,8 +355,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (user_font_rescale,
+	    "Tests drawing text with user defined widths",
+	    "user-font, font", /* keywords */
+	    NULL, /* requirements */
+	    WIDTH, HEIGHT,
+	    NULL, draw)
diff --git a/test/user-font.c b/test/user-font.c
index 6688ce0..38e2b1d 100644
--- a/test/user-font.c
+++ b/test/user-font.c
@@ -38,19 +38,6 @@
 #define HEIGHT ((TEXT_SIZE + 2*BORDER)*2)
 #define TEXT   "geez... cairo user-font"
 
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "user-font",
-    "Tests user font feature",
-#ifndef ROTATED
-    WIDTH, HEIGHT,
-#else
-    WIDTH, WIDTH,
-#endif
-    draw
-};
-
 #define END_GLYPH 0
 #define STROKE 126
 #define CLOSE 127
@@ -268,8 +255,13 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (user_font,
+	    "Tests user font feature",
+	    "font, user-font", /* keywords */
+	    "cairo >= 1.7.4", /* requirements */
+#ifndef ROTATED
+	    WIDTH, HEIGHT,
+#else
+	    WIDTH, WIDTH,
+#endif
+	    NULL, draw)
diff --git a/test/xlib-expose-event.c b/test/xlib-expose-event.c
index fd0bbcb..a2bda1a 100644
--- a/test/xlib-expose-event.c
+++ b/test/xlib-expose-event.c
@@ -46,7 +46,7 @@
 #define SIZE 160
 #define NLOOPS 10
 
-static const char	png_filename[]	= "romedalen.png";
+static const char *png_filename = "romedalen.png";
 
 static cairo_bool_t
 check_visual (Display *dpy)
@@ -203,10 +203,9 @@ compare (const cairo_test_context_t *ctx, cairo_surface_t *surface)
 	CAIRO_TEST_SUCCESS : CAIRO_TEST_FAILURE;
 }
 
-int
-main (void)
+static cairo_test_status_t
+preamble (cairo_test_context_t *ctx)
 {
-    cairo_test_context_t ctx;
     Display *dpy;
     Drawable drawable;
     int screen;
@@ -215,18 +214,17 @@ main (void)
     int i, j;
     cairo_test_status_t result = CAIRO_TEST_UNTESTED;
 
-    cairo_test_init (&ctx, "xlib-expose-event");
-    if (! cairo_test_is_target_enabled (&ctx, "xlib"))
+    if (! cairo_test_is_target_enabled (ctx, "xlib"))
 	goto CLEANUP_TEST;
 
     dpy = XOpenDisplay (NULL);
     if (dpy == NULL) {
-	cairo_test_log (&ctx, "xlib-expose-event: Cannot open display, skipping\n");
+	cairo_test_log (ctx, "xlib-expose-event: Cannot open display, skipping\n");
 	goto CLEANUP_TEST;
     }
 
     if (! check_visual (dpy)) {
-	cairo_test_log (&ctx, "xlib-expose-event: default visual is not RGB24 or BGR24, skipping\n");
+	cairo_test_log (ctx, "xlib-expose-event: default visual is not RGB24 or BGR24, skipping\n");
 	goto CLEANUP_DISPLAY;
     }
 
@@ -238,7 +236,7 @@ main (void)
 					 DefaultVisual (dpy, screen),
 					 SIZE, SIZE);
     clear (surface);
-    draw (&ctx, surface, NULL, 0);
+    draw (ctx, surface, NULL, 0);
     for (i = 0; i < NLOOPS; i++) {
 	for (j = 0; j < NLOOPS; j++) {
 	    region[0].x = i * SIZE / NLOOPS;
@@ -261,11 +259,11 @@ main (void)
 	    region[3].width = SIZE / 4;
 	    region[3].height = SIZE / 4;
 
-	    draw (&ctx, surface, region, 4);
+	    draw (ctx, surface, region, 4);
 	}
     }
 
-    result = compare (&ctx, surface);
+    result = compare (ctx, surface);
 
     cairo_surface_destroy (surface);
 
@@ -275,8 +273,12 @@ main (void)
     XCloseDisplay (dpy);
 
   CLEANUP_TEST:
-    cairo_test_fini (&ctx);
-
     return result;
 }
 
+CAIRO_TEST (xlib_expose_event,
+	    "Emulate a typical expose event",
+	    "xlib", /* keywords */
+	    NULL, /* requirements */
+	    0, 0,
+	    preamble, NULL)
diff --git a/test/xlib-surface-source.c b/test/xlib-surface-source.c
index 3c33516..b99f088 100644
--- a/test/xlib-surface-source.c
+++ b/test/xlib-surface-source.c
@@ -29,7 +29,6 @@
 #include <cairo-xlib-xrender.h>
 #endif
 
-#define NAME "xlib"
 #include "surface-source.c"
 
 static cairo_user_data_key_t closure_key;
@@ -82,3 +81,10 @@ create_source_surface (int size)
     return NULL;
 #endif
 }
+
+CAIRO_TEST (xlib_surface_source,
+	    "Test using a Xlib surface as the source",
+	    "source", /* keywords */
+	    NULL, /* requirements */
+	    SIZE, SIZE,
+	    preamble, draw)
diff --git a/test/xlib-surface.c b/test/xlib-surface.c
index 20c715e..a7ff020 100644
--- a/test/xlib-surface.c
+++ b/test/xlib-surface.c
@@ -276,21 +276,19 @@ check_visual (Display *dpy)
 
 #undef xcalloc
 static void *
-xcalloc (cairo_test_context_t *ctx, size_t a, size_t b)
+xcalloc (const cairo_test_context_t *ctx, size_t a, size_t b)
 {
     void *ptr = calloc (a, b);
     if (ptr == NULL) {
 	cairo_test_log (ctx, "xlib-surface: unable to allocate memory, skipping\n");
-	cairo_test_fini (ctx);
-	exit (CAIRO_TEST_SUCCESS);
+	abort ();
     }
     return ptr;
 }
 
-int
-main (void)
+static cairo_test_status_t
+preamble (cairo_test_context_t *ctx)
 {
-    cairo_test_context_t ctx;
     Display *dpy;
     unsigned char *reference_data;
     unsigned char *test_data;
@@ -302,26 +300,25 @@ main (void)
     cairo_test_status_t status, result = CAIRO_TEST_UNTESTED;
     int stride;
 
-    cairo_test_init (&ctx, "xlib-surface");
-    if (! cairo_test_is_target_enabled (&ctx, "xlib"))
+    if (! cairo_test_is_target_enabled (ctx, "xlib"))
 	goto CLEANUP_TEST;
 
     dpy = XOpenDisplay (NULL);
     if (!dpy) {
-	cairo_test_log (&ctx, "xlib-surface: Cannot open display, skipping\n");
+	cairo_test_log (ctx, "xlib-surface: Cannot open display, skipping\n");
 	goto CLEANUP_TEST;
     }
 
     if (!check_visual (dpy)) {
-	cairo_test_log (&ctx, "xlib-surface: default visual is not RGB24 or BGR24, skipping\n");
+	cairo_test_log (ctx, "xlib-surface: default visual is not RGB24 or BGR24, skipping\n");
 	goto CLEANUP_DISPLAY;
     }
 
     stride = cairo_format_stride_for_width (CAIRO_FORMAT_RGB24, SIZE);
 
-    reference_data = xcalloc (&ctx, SIZE, stride);
-    test_data = xcalloc (&ctx, SIZE, stride);
-    diff_data = xcalloc (&ctx, SIZE, stride);
+    reference_data = xcalloc (ctx, SIZE, stride);
+    test_data = xcalloc (ctx, SIZE, stride);
+    diff_data = xcalloc (ctx, SIZE, stride);
 
     reference_surface = cairo_image_surface_create_for_data (reference_data,
 							     CAIRO_FORMAT_RGB24,
@@ -336,7 +333,7 @@ main (void)
     for (set_size = 0; set_size <= 1; set_size++)
 	for (use_pixmap = 0; use_pixmap <= 1; use_pixmap++)
 	    for (offscreen = 0; offscreen <= 1; offscreen++) {
-		status = do_test (&ctx, dpy,
+		status = do_test (ctx, dpy,
 				  reference_data, test_data, diff_data,
 				  1, use_pixmap, set_size, offscreen);
 		if (status)
@@ -346,7 +343,7 @@ main (void)
     for (set_size = 0; set_size <= 1; set_size++)
 	for (use_pixmap = 0; use_pixmap <= 1; use_pixmap++)
 	    for (offscreen = 0; offscreen <= 1; offscreen++) {
-		status = do_test (&ctx, dpy,
+		status = do_test (ctx, dpy,
 				  reference_data, test_data, diff_data,
 				  0, use_pixmap, set_size, offscreen);
 		if (status)
@@ -361,7 +358,12 @@ main (void)
     XCloseDisplay (dpy);
 
   CLEANUP_TEST:
-    cairo_test_fini (&ctx);
-
     return result;
 }
+
+CAIRO_TEST (xlib_surface,
+	    "Check creating surfaces for various XWindows",
+	    "xlib", /* keywords */
+	    NULL, /* requirements */
+	    0, 0,
+	    preamble, NULL)
diff --git a/test/zero-alpha.c b/test/zero-alpha.c
index 84658f7..1c7c94b 100644
--- a/test/zero-alpha.c
+++ b/test/zero-alpha.c
@@ -42,15 +42,6 @@
  * 2006-06-13 Paul Giblock reports that this only happens with the
  * xlib backend, and then only on some systems.
  */
-static cairo_test_draw_function_t draw;
-
-static const cairo_test_t test = {
-    "zero-alpha",
-    "Testing that drawing with zero alpha has no effect",
-    SIZE, SIZE,
-    draw
-};
-
 static cairo_test_status_t
 draw (cairo_t *cr, int width, int height)
 {
@@ -95,8 +86,9 @@ draw (cairo_t *cr, int width, int height)
     return CAIRO_TEST_SUCCESS;
 }
 
-int
-main (void)
-{
-    return cairo_test (&test);
-}
+CAIRO_TEST (zero_alpha,
+	    "Testing that drawing with zero alpha has no effect",
+	    "alpha", /* keywords */
+	    NULL, /* requirements */
+	    SIZE, SIZE,
+	    NULL, draw)
commit 8457972d40088cda165f31fdd7bd9b4c19c6e095
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri Oct 31 02:16:54 2008 +0000

    [type3] Whitespace.
    
    Tightly scope the output stream.

diff --git a/src/cairo-type3-glyph-surface.c b/src/cairo-type3-glyph-surface.c
index ee516f5..58048ac 100644
--- a/src/cairo-type3-glyph-surface.c
+++ b/src/cairo-type3-glyph-surface.c
@@ -445,7 +445,6 @@ _cairo_type3_glyph_surface_emit_glyph (void		     *abstract_surface,
     cairo_scaled_glyph_t *scaled_glyph;
     cairo_status_t status, status2;
     double x_advance, y_advance;
-    cairo_output_stream_t *mem_stream;
     cairo_matrix_t font_matrix_inverse;
 
     _cairo_type3_glyph_surface_set_stream (surface, stream);
@@ -495,6 +494,8 @@ _cairo_type3_glyph_surface_emit_glyph (void		     *abstract_surface,
 				 - _cairo_fixed_to_double (bbox->p1.y));
 
     if (status == CAIRO_STATUS_SUCCESS) {
+	cairo_output_stream_t *mem_stream;
+
 	mem_stream = _cairo_memory_stream_create ();
 	_cairo_type3_glyph_surface_set_stream (surface, mem_stream);
 
commit 08f4d49a9464bc19bc2ca7f2356a6eb8d62f5daf
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri Oct 31 02:03:41 2008 +0000

    [xlib] Intialise clip_dirty.
    
    Eeek, forgot to set the clip_dirty to 0 on construction.

diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c
index 0d79292..7efe828 100644
--- a/src/cairo-xlib-surface.c
+++ b/src/cairo-xlib-surface.c
@@ -2621,6 +2621,7 @@ _cairo_xlib_surface_create_internal (Display		       *dpy,
     surface->have_clip_rects = FALSE;
     surface->clip_rects = surface->embedded_clip_rects;
     surface->num_clip_rects = 0;
+    surface->clip_dirty = 0;
 
     /*
      * Compute the pixel format masks from either a XrenderFormat or


More information about the cairo-commit mailing list