2 * Copyright © 2008 Chris Wilson
4 * Permission to use, copy, modify, distribute, and sell this software
5 * and its documentation for any purpose is hereby granted without
6 * fee, provided that the above copyright notice appear in all copies
7 * and that both that copyright notice and this permission notice
8 * appear in supporting documentation, and that the name of
9 * Chris Wilson not be used in advertising or publicity pertaining to
10 * distribution of the software without specific, written prior
11 * permission. Chris Wilson makes no representations about the
12 * suitability of this software for any purpose. It is provided "as
13 * is" without express or implied warranty.
15 * CHRIS WILSON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
16 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17 * FITNESS, IN NO EVENT SHALL CHRIS WILSON BE LIABLE FOR ANY SPECIAL,
18 * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
19 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
20 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
21 * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 * Author: Chris Wilson <chris@chris-wilson.co.uk>
26 #include "cairo-test-private.h"
27 #include "cairo-boilerplate-getopt.h"
29 /* get the "real" version info instead of dummy cairo-version.h */
30 #undef CAIRO_VERSION_H
31 #undef CAIRO_VERSION_MAJOR
32 #undef CAIRO_VERSION_MINOR
33 #undef CAIRO_VERSION_MICRO
34 #include "../cairo-version.h"
36 #include <pixman.h> /* for version information */
38 #define SHOULD_FORK HAVE_FORK && HAVE_WAITPID
46 #include <sys/types.h>
56 #define RUNNING_ON_VALGRIND 0
63 typedef struct _cairo_test_list {
64 const cairo_test_t *test;
65 struct _cairo_test_list *next;
68 typedef struct _cairo_test_runner {
69 cairo_test_context_t base;
71 unsigned int num_device_offsets;
72 unsigned int num_device_scales;
82 cairo_test_list_t *crashes_preamble;
83 cairo_test_list_t *errors_preamble;
84 cairo_test_list_t *fails_preamble;
86 cairo_test_list_t **crashes_per_target;
87 cairo_test_list_t **errors_per_target;
88 cairo_test_list_t **fails_per_target;
90 int *num_failed_per_target;
91 int *num_error_per_target;
92 int *num_crashed_per_target;
94 cairo_bool_t foreground;
95 cairo_bool_t exit_on_failure;
96 cairo_bool_t list_only;
97 cairo_bool_t full_test;
98 cairo_bool_t keyword_match;
100 cairo_bool_t force_pass;
101 } cairo_test_runner_t;
106 } cairo_test_compare_op_t;
108 static cairo_test_list_t *tests;
110 static void CAIRO_BOILERPLATE_PRINTF_FORMAT(2,3)
111 _log (cairo_test_context_t *ctx,
122 cairo_test_logv (ctx, fmt, ap);
126 static cairo_test_list_t *
127 _list_prepend (cairo_test_list_t *head, const cairo_test_t *test)
129 cairo_test_list_t *list;
131 list = xmalloc (sizeof (cairo_test_list_t));
139 static cairo_test_list_t *
140 _list_reverse (cairo_test_list_t *head)
142 cairo_test_list_t *list, *next;
144 for (list = head, head = NULL; list != NULL; list = next) {
154 _list_free (cairo_test_list_t *list)
156 while (list != NULL) {
157 cairo_test_list_t *next = list->next;
164 is_running_under_debugger (void)
166 #if HAVE_UNISTD_H && HAVE_LIBGEN_H && __linux__
169 sprintf (buf, "/proc/%d/exe", getppid ());
170 if (readlink (buf, buf, sizeof (buf)) != -1 &&
171 strncmp (basename (buf), "gdb", 3) == 0)
177 if (RUNNING_ON_VALGRIND)
184 static cairo_test_status_t
185 _cairo_test_wait (pid_t pid)
189 if (waitpid (pid, &exitcode, 0) != pid)
190 return CAIRO_TEST_CRASHED;
192 if (WIFSIGNALED (exitcode)) {
193 switch (WTERMSIG (exitcode)) {
198 return CAIRO_TEST_UNTESTED;
200 return CAIRO_TEST_CRASHED;
204 return WEXITSTATUS (exitcode);
208 static cairo_test_status_t
209 _cairo_test_runner_preamble (cairo_test_runner_t *runner,
210 cairo_test_context_t *ctx)
213 if (! runner->foreground) {
216 switch ((pid = fork ())) {
218 return CAIRO_TEST_UNTESTED;
221 exit (ctx->test->preamble (ctx));
224 return _cairo_test_wait (pid);
228 return ctx->test->preamble (ctx);
231 static cairo_test_status_t
232 _cairo_test_runner_draw (cairo_test_runner_t *runner,
233 cairo_test_context_t *ctx,
234 const cairo_boilerplate_target_t *target,
235 cairo_bool_t similar,
236 int device_offset, int device_scale)
239 if (! runner->foreground) {
242 switch ((pid = fork ())) {
244 return CAIRO_TEST_UNTESTED;
247 exit (_cairo_test_context_run_for_target (ctx, target,
248 similar, device_offset, device_scale));
251 return _cairo_test_wait (pid);
255 return _cairo_test_context_run_for_target (ctx, target,
256 similar, device_offset, device_scale);
260 append_argv (int *argc, char ***argv, const char *str)
280 *argv = xmalloc (olen);
282 olen = sizeof (char *) * (args_to_add + *argc);
283 for (i = 0; i < old_argc; i++) {
284 len = strlen (old_argv[i]) + 1;
286 (*argv)[i] = (char *) *argv + olen;
287 memcpy ((*argv)[i], old_argv[i], len);
293 while ((t = strpbrk (s, " \t,:;")) != NULL) {
297 (*argv)[i] = (char *) *argv + olen;
298 memcpy ((*argv)[i], s, len);
299 (*argv)[i][len] = '\0';
301 olen += sizeof (char *);
310 len = strlen (s) + 1;
312 (*argv)[i] = (char *) *argv + olen;
313 memcpy ((*argv)[i], s, len);
315 olen += sizeof (char *);
321 } while (doit++ == FALSE);
326 usage (const char *argv0)
329 "Usage: %s [-afkxsl] [test-names|keywords ...]\n"
331 "Run the cairo conformance test suite over the given tests (all by default)\n"
332 "The command-line arguments are interpreted as follows:\n"
334 " -a all; run the full set of tests. By default the test suite\n"
335 " skips similar surface and device offset testing.\n"
336 " -f foreground; do not fork\n"
337 " -k match tests by keyword\n"
338 " -l list only; just list selected test case names without executing\n"
339 " -s include slow, long running tests\n"
340 " -x exit on first failure\n"
342 "If test names are given they are used as matches either to a specific\n"
343 "test case or to a keyword, so a command such as\n"
344 "\"%s -k text\" can be used to run all text test cases, and\n"
345 "\"%s text-transform\" to run the individual case.\n",
346 argv0, argv0, argv0);
350 _parse_cmdline (cairo_test_runner_t *runner, int *argc, char **argv[])
355 c = _cairo_getopt (*argc, *argv, ":afklsx");
361 runner->full_test = ~0;
364 runner->foreground = TRUE;
367 runner->keyword_match = TRUE;
370 runner->list_only = TRUE;
376 runner->exit_on_failure = TRUE;
379 fprintf (stderr, "Internal error: unhandled option: %c\n", c);
392 _runner_init (cairo_test_runner_t *runner)
394 cairo_test_init (&runner->base, "cairo-test-suite", ".");
396 runner->passed = TRUE;
398 runner->fails_preamble = NULL;
399 runner->crashes_preamble = NULL;
400 runner->errors_preamble = NULL;
402 runner->fails_per_target = xcalloc (sizeof (cairo_test_list_t *),
403 runner->base.num_targets);
404 runner->crashes_per_target = xcalloc (sizeof (cairo_test_list_t *),
405 runner->base.num_targets);
406 runner->errors_per_target = xcalloc (sizeof (cairo_test_list_t *),
407 runner->base.num_targets);
408 runner->num_failed_per_target = xcalloc (sizeof (int),
409 runner->base.num_targets);
410 runner->num_error_per_target = xcalloc (sizeof (int),
411 runner->base.num_targets);
412 runner->num_crashed_per_target = xcalloc (sizeof (int),
413 runner->base.num_targets);
417 _runner_print_versions (cairo_test_runner_t *runner)
420 "Compiled against cairo %s, running on %s.\n",
421 CAIRO_VERSION_STRING, cairo_version_string ());
423 "Compiled against pixman %s, running on %s.\n",
424 PIXMAN_VERSION_STRING, pixman_version_string ());
426 fflush (runner->base.log_file);
430 _runner_print_summary (cairo_test_runner_t *runner)
433 "%d Passed, %d Failed [%d crashed, %d expected], %d Skipped\n",
436 runner->num_failed + runner->num_crashed + runner->num_xfailed,
440 runner->num_skipped);
444 _runner_print_details (cairo_test_runner_t *runner)
446 cairo_test_list_t *list;
449 if (runner->crashes_preamble) {
452 for (list = runner->crashes_preamble; list != NULL; list = list->next)
455 _log (&runner->base, "Preamble: %d crashed! -", count);
457 for (list = runner->crashes_preamble; list != NULL; list = list->next) {
458 char *name = cairo_test_get_name (list->test);
459 _log (&runner->base, " %s", name);
462 _log (&runner->base, "\n");
464 if (runner->errors_preamble) {
467 for (list = runner->errors_preamble; list != NULL; list = list->next)
470 _log (&runner->base, "Preamble: %d error -", count);
472 for (list = runner->errors_preamble; list != NULL; list = list->next) {
473 char *name = cairo_test_get_name (list->test);
474 _log (&runner->base, " %s", name);
477 _log (&runner->base, "\n");
479 if (runner->fails_preamble) {
482 for (list = runner->fails_preamble; list != NULL; list = list->next)
485 _log (&runner->base, "Preamble: %d failed -", count);
487 for (list = runner->fails_preamble; list != NULL; list = list->next) {
488 char *name = cairo_test_get_name (list->test);
489 _log (&runner->base, " %s", name);
492 _log (&runner->base, "\n");
495 for (n = 0; n < runner->base.num_targets; n++) {
496 const cairo_boilerplate_target_t *target;
498 target = runner->base.targets_to_test[n];
499 if (runner->num_crashed_per_target[n]) {
500 _log (&runner->base, "%s (%s): %d crashed! -",
502 cairo_boilerplate_content_name (target->content),
503 runner->num_crashed_per_target[n]);
505 for (list = runner->crashes_per_target[n];
509 char *name = cairo_test_get_name (list->test);
510 _log (&runner->base, " %s", name);
513 _log (&runner->base, "\n");
515 if (runner->num_error_per_target[n]) {
516 _log (&runner->base, "%s (%s): %d error -",
518 cairo_boilerplate_content_name (target->content),
519 runner->num_error_per_target[n]);
521 for (list = runner->errors_per_target[n];
525 char *name = cairo_test_get_name (list->test);
526 _log (&runner->base, " %s", name);
529 _log (&runner->base, "\n");
532 if (runner->num_failed_per_target[n]) {
533 _log (&runner->base, "%s (%s): %d failed -",
535 cairo_boilerplate_content_name (target->content),
536 runner->num_failed_per_target[n]);
538 for (list = runner->fails_per_target[n];
542 char *name = cairo_test_get_name (list->test);
543 _log (&runner->base, " %s", name);
546 _log (&runner->base, "\n");
552 _runner_print_results (cairo_test_runner_t *runner)
554 _runner_print_summary (runner);
555 _runner_print_details (runner);
557 if (! runner->passed && ! runner->num_crashed) {
560 "Note: These failures may be due to external factors.\n"
561 "Please read test/README -- \"Getting the elusive zero failures\".\n");
565 static cairo_test_status_t
566 _runner_fini (cairo_test_runner_t *runner)
570 _list_free (runner->crashes_preamble);
571 _list_free (runner->errors_preamble);
572 _list_free (runner->fails_preamble);
574 for (n = 0; n < runner->base.num_targets; n++) {
575 _list_free (runner->crashes_per_target[n]);
576 _list_free (runner->errors_per_target[n]);
577 _list_free (runner->fails_per_target[n]);
579 free (runner->crashes_per_target);
580 free (runner->errors_per_target);
581 free (runner->fails_per_target);
583 free (runner->num_crashed_per_target);
584 free (runner->num_error_per_target);
585 free (runner->num_failed_per_target);
587 cairo_test_fini (&runner->base);
589 if (runner->force_pass)
590 return CAIRO_TEST_SUCCESS;
592 return runner->num_failed + runner->num_crashed ?
594 runner->num_passed + runner->num_xfailed ?
595 CAIRO_TEST_SUCCESS : CAIRO_TEST_UNTESTED;
599 _version_compare (int a, cairo_test_compare_op_t op, int b)
602 case GT: return a > b;
603 case GE: return a >= b;
604 default: return FALSE;
610 _get_required_version (const char *str,
611 cairo_test_compare_op_t *op,
619 if (strncmp (str, ">=", 2) == 0) {
622 } else if (strncmp (str, ">", 1) == 0) {
631 if (sscanf (str, "%d.%d.%d", major, minor, micro) != 3) {
633 if (sscanf (str, "%d.%d", major, minor) != 2)
641 _has_required_cairo_version (const char *str)
643 cairo_test_compare_op_t op;
644 int major, minor, micro;
646 if (! _get_required_version (str + 5 /* advance over "cairo" */,
647 &op, &major, &minor, µ))
649 fprintf (stderr, "unrecognised cairo version requirement '%s'\n", str);
653 return _version_compare (cairo_version (),
655 CAIRO_VERSION_ENCODE (major, minor, micro));
659 _has_required_ghostscript_version (const char *str)
661 #if ! CAIRO_CAN_TEST_PS_SURFACE
665 str += 2; /* advance over "gs" */
671 _has_required_poppler_version (const char *str)
673 #if ! CAIRO_CAN_TEST_PDF_SURFACE
677 str += 7; /* advance over "poppler" */
683 _has_required_rsvg_version (const char *str)
685 #if ! CAIRO_CAN_TEST_SVG_SURFACE
689 str += 4; /* advance over "rsvg" */
694 #define TEST_SIMILAR 0x1
695 #define TEST_OFFSET 0x2
696 #define TEST_SCALE 0x4
698 main (int argc, char **argv)
700 cairo_test_runner_t runner;
701 cairo_test_list_t *test_list;
702 cairo_test_status_t *target_status;
703 unsigned int n, m, k;
706 char *cairo_tests_env;
709 /* We don't want an assert dialog, we want stderr */
710 _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
711 _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
714 _cairo_test_runner_register_tests ();
715 tests = _list_reverse (tests);
717 memset (&runner, 0, sizeof (runner));
718 runner.num_device_offsets = 1;
719 runner.num_device_scales = 1;
721 if (is_running_under_debugger ())
722 runner.foreground = TRUE;
724 if (getenv ("CAIRO_TEST_MODE")) {
725 const char *env = getenv ("CAIRO_TEST_MODE");
727 if (strstr (env, "full")) {
728 runner.full_test = ~0;
730 if (strstr (env, "similar")) {
731 runner.full_test |= TEST_SIMILAR;
733 if (strstr (env, "offset")) {
734 runner.full_test |= TEST_OFFSET;
736 if (strstr (env, "scale")) {
737 runner.full_test |= TEST_SCALE;
739 if (strstr (env, "foreground")) {
740 runner.foreground = TRUE;
742 if (strstr (env, "exit-on-failure")) {
743 runner.exit_on_failure = TRUE;
747 if (getenv ("CAIRO_TEST_FORCE_PASS")) {
748 const char *env = getenv ("CAIRO_TEST_FORCE_PASS");
750 runner.force_pass = atoi (env);
753 _parse_cmdline (&runner, &argc, &argv);
755 cairo_tests_env = getenv("CAIRO_TESTS");
756 append_argv (&argc, &argv, cairo_tests_env);
758 if (runner.full_test & TEST_OFFSET) {
759 runner.num_device_offsets = 2;
761 if (runner.full_test & TEST_SCALE) {
762 runner.num_device_scales = 2;
765 target_status = NULL; /* silence the compiler */
766 if (! runner.list_only) {
767 _runner_init (&runner);
768 _runner_print_versions (&runner);
769 target_status = xmalloc (sizeof (cairo_test_status_t) *
770 runner.base.num_targets);
773 for (test_list = tests; test_list != NULL; test_list = test_list->next) {
774 const cairo_test_t *test = test_list->test;
775 cairo_test_context_t ctx;
776 cairo_test_status_t status;
777 cairo_bool_t failed = FALSE, xfailed = FALSE, error = FALSE, crashed = FALSE, skipped = TRUE;
778 cairo_bool_t in_preamble = FALSE;
779 char *name = cairo_test_get_name (test);
782 /* check for restricted runs */
784 cairo_bool_t found = FALSE;
785 const char *keywords = test->keywords;
787 for (i = 0; i < argc; i++) {
788 const char *match = argv[i];
789 cairo_bool_t invert = match[0] == '!';
793 if (runner.keyword_match) {
794 if (keywords != NULL && strstr (keywords, match) != NULL) {
801 /* exact match on test name */
802 if (strcmp (name, match) == 0) {
817 /* check to see if external requirements match */
818 if (test->requirements != NULL) {
819 const char *requirements = test->requirements;
822 str = strstr (requirements, "slow");
823 if (str != NULL && ! runner.slow) {
824 if (runner.list_only)
830 str = strstr (requirements, "cairo");
831 if (str != NULL && ! _has_required_cairo_version (str)) {
832 if (runner.list_only)
838 str = strstr (requirements, "gs");
839 if (str != NULL && ! _has_required_ghostscript_version (str)) {
840 if (runner.list_only)
846 str = strstr (requirements, "poppler");
847 if (str != NULL && ! _has_required_poppler_version (str)) {
848 if (runner.list_only)
854 str = strstr (requirements, "rsvg");
855 if (str != NULL && ! _has_required_rsvg_version (str)) {
856 if (runner.list_only)
863 if (runner.list_only) {
864 printf ("%s ", name);
868 _cairo_test_context_init_for_test (&ctx, &runner.base, test);
869 memset (target_status, 0,
870 sizeof (cairo_test_status_t) * ctx.num_targets);
872 if (ctx.test->preamble != NULL) {
873 status = _cairo_test_runner_preamble (&runner, &ctx);
875 case CAIRO_TEST_SUCCESS:
880 case CAIRO_TEST_XFAILURE:
886 case CAIRO_TEST_FAILURE:
887 runner.fails_preamble = _list_prepend (runner.fails_preamble,
893 case CAIRO_TEST_ERROR:
894 runner.errors_preamble = _list_prepend (runner.errors_preamble,
900 case CAIRO_TEST_NO_MEMORY:
901 case CAIRO_TEST_CRASHED:
902 runner.crashes_preamble = _list_prepend (runner.crashes_preamble,
908 case CAIRO_TEST_UNTESTED:
913 if (ctx.test->draw == NULL)
916 for (n = 0; n < ctx.num_targets; n++) {
917 const cairo_boilerplate_target_t *target;
918 cairo_bool_t target_failed = FALSE,
919 target_xfailed = FALSE,
920 target_error = FALSE,
921 target_crashed = FALSE,
922 target_skipped = TRUE;
923 cairo_test_similar_t has_similar;
925 target = ctx.targets_to_test[n];
927 has_similar = runner.full_test & TEST_SIMILAR ?
928 cairo_test_target_has_similar (&ctx, target) :
930 for (m = 0; m < runner.num_device_offsets; m++) {
931 for (k = 0; k < runner.num_device_scales; k++) {
932 int dev_offset = m * 25;
933 int dev_scale = k + 1;
934 cairo_test_similar_t similar;
936 for (similar = DIRECT; similar <= has_similar; similar++) {
937 status = _cairo_test_runner_draw (&runner, &ctx, target,
938 similar, dev_offset, dev_scale);
940 case CAIRO_TEST_SUCCESS:
941 target_skipped = FALSE;
943 case CAIRO_TEST_XFAILURE:
944 target_xfailed = TRUE;
947 case CAIRO_TEST_FAILURE:
948 target_failed = TRUE;
950 case CAIRO_TEST_ERROR:
953 case CAIRO_TEST_NO_MEMORY:
954 case CAIRO_TEST_CRASHED:
955 target_crashed = TRUE;
957 case CAIRO_TEST_UNTESTED:
964 if (target_crashed) {
965 target_status[n] = CAIRO_TEST_CRASHED;
966 runner.num_crashed_per_target[n]++;
967 runner.crashes_per_target[n] = _list_prepend (runner.crashes_per_target[n],
970 } else if (target_error) {
971 target_status[n] = CAIRO_TEST_ERROR;
972 runner.num_error_per_target[n]++;
973 runner.errors_per_target[n] = _list_prepend (runner.errors_per_target[n],
977 } else if (target_failed) {
978 target_status[n] = CAIRO_TEST_FAILURE;
979 runner.num_failed_per_target[n]++;
980 runner.fails_per_target[n] = _list_prepend (runner.fails_per_target[n],
984 } else if (target_xfailed) {
985 target_status[n] = CAIRO_TEST_XFAILURE;
987 } else if (target_skipped) {
988 target_status[n] = CAIRO_TEST_UNTESTED;
990 target_status[n] = CAIRO_TEST_SUCCESS;
996 cairo_test_fini (&ctx);
1000 if (! in_preamble) {
1002 for (n = 0 ; n < runner.base.num_targets; n++) {
1003 if (target_status[n] == CAIRO_TEST_CRASHED) {
1004 if (strstr (targets,
1005 runner.base.targets_to_test[n]->name) == NULL)
1007 len += snprintf (targets + len, sizeof (targets) - len,
1009 runner.base.targets_to_test[n]->name);
1013 targets[len-2] = '\0';
1014 _log (&runner.base, "\n%s: CRASH! (%s)\n", name, targets);
1016 _log (&runner.base, "\n%s: CRASH!\n", name);
1018 runner.num_crashed++;
1019 runner.passed = FALSE;
1021 if (! in_preamble) {
1023 for (n = 0 ; n < runner.base.num_targets; n++) {
1024 if (target_status[n] == CAIRO_TEST_ERROR) {
1025 if (strstr (targets,
1026 runner.base.targets_to_test[n]->name) == NULL)
1028 len += snprintf (targets + len,
1029 sizeof (targets) - len,
1031 runner.base.targets_to_test[n]->name);
1035 targets[len-2] = '\0';
1036 _log (&runner.base, "%s: ERROR (%s)\n", name, targets);
1038 _log (&runner.base, "%s: ERROR\n", name);
1041 runner.passed = FALSE;
1042 } else if (failed) {
1043 if (! in_preamble) {
1045 for (n = 0 ; n < runner.base.num_targets; n++) {
1046 if (target_status[n] == CAIRO_TEST_FAILURE) {
1047 if (strstr (targets,
1048 runner.base.targets_to_test[n]->name) == NULL)
1050 len += snprintf (targets + len,
1051 sizeof (targets) - len,
1053 runner.base.targets_to_test[n]->name);
1057 targets[len-2] = '\0';
1058 _log (&runner.base, "%s: FAIL (%s)\n", name, targets);
1060 _log (&runner.base, "%s: FAIL\n", name);
1062 runner.num_failed++;
1063 runner.passed = FALSE;
1064 } else if (xfailed) {
1065 _log (&runner.base, "%s: XFAIL\n", name);
1066 runner.num_xfailed++;
1067 } else if (skipped) {
1068 _log (&runner.base, "%s: UNTESTED\n", name);
1069 runner.num_skipped++;
1071 _log (&runner.base, "%s: PASS\n", name);
1072 runner.num_passed++;
1074 fflush (runner.base.log_file);
1078 if (runner.exit_on_failure && ! runner.passed)
1083 if (cairo_tests_env)
1086 if (runner.list_only) {
1088 return CAIRO_TEST_SUCCESS;
1091 for (n = 0 ; n < runner.base.num_targets; n++) {
1092 runner.crashes_per_target[n] = _list_reverse (runner.crashes_per_target[n]);
1093 runner.errors_per_target[n] = _list_reverse (runner.errors_per_target[n]);
1094 runner.fails_per_target[n] = _list_reverse (runner.fails_per_target[n]);
1097 _runner_print_results (&runner);
1100 free (target_status);
1101 return _runner_fini (&runner);
1105 cairo_test_register (cairo_test_t *test)
1107 tests = _list_prepend (tests, test);