2008-09-03 16:38:03 +01:00
|
|
|
/*
|
|
|
|
|
* 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@chris-wilson.co.uk>
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "cairo-test-private.h"
|
|
|
|
|
#include "cairo-boilerplate-getopt.h"
|
|
|
|
|
|
|
|
|
|
#include <pixman.h> /* for version information */
|
|
|
|
|
|
2011-12-15 13:04:02 -08:00
|
|
|
#define SHOULD_FORK HAVE_FORK && HAVE_WAITPID
|
2008-09-03 16:38:03 +01:00
|
|
|
#if HAVE_UNISTD_H
|
|
|
|
|
#include <unistd.h>
|
|
|
|
|
#endif
|
2020-02-03 21:24:25 +01:00
|
|
|
#if SHOULD_FORK
|
2008-09-03 16:38:03 +01:00
|
|
|
#if HAVE_SIGNAL_H
|
|
|
|
|
#include <signal.h>
|
|
|
|
|
#endif
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
|
#include <sys/wait.h>
|
|
|
|
|
#endif
|
2009-08-22 17:53:59 +01:00
|
|
|
#if HAVE_LIBGEN_H
|
|
|
|
|
#include <libgen.h>
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if HAVE_VALGRIND
|
|
|
|
|
#include <valgrind.h>
|
|
|
|
|
#else
|
|
|
|
|
#define RUNNING_ON_VALGRIND 0
|
|
|
|
|
#endif
|
2008-09-03 16:38:03 +01:00
|
|
|
|
2009-02-10 17:58:28 -05:00
|
|
|
#ifdef _MSC_VER
|
|
|
|
|
#include <crtdbg.h>
|
|
|
|
|
#endif
|
|
|
|
|
|
2008-09-03 16:38:03 +01:00
|
|
|
typedef struct _cairo_test_list {
|
|
|
|
|
const cairo_test_t *test;
|
|
|
|
|
struct _cairo_test_list *next;
|
|
|
|
|
} cairo_test_list_t;
|
|
|
|
|
|
2008-11-19 08:37:26 +00:00
|
|
|
typedef struct _cairo_test_runner {
|
|
|
|
|
cairo_test_context_t base;
|
|
|
|
|
|
|
|
|
|
unsigned int num_device_offsets;
|
2013-06-03 15:38:22 +02:00
|
|
|
unsigned int num_device_scales;
|
2008-11-19 08:37:26 +00:00
|
|
|
|
2009-05-09 19:01:06 +01:00
|
|
|
cairo_bool_t passed;
|
2008-11-19 08:37:26 +00:00
|
|
|
int num_passed;
|
|
|
|
|
int num_skipped;
|
|
|
|
|
int num_failed;
|
|
|
|
|
int num_xfailed;
|
2010-06-11 09:12:16 +01:00
|
|
|
int num_error;
|
2008-11-19 08:37:26 +00:00
|
|
|
int num_crashed;
|
|
|
|
|
|
2021-04-17 10:01:17 +00:00
|
|
|
unsigned int num_ignored_via_env;
|
|
|
|
|
|
2009-07-20 13:44:48 +01:00
|
|
|
cairo_test_list_t *crashes_preamble;
|
2010-06-11 09:12:16 +01:00
|
|
|
cairo_test_list_t *errors_preamble;
|
2009-07-20 13:44:48 +01:00
|
|
|
cairo_test_list_t *fails_preamble;
|
|
|
|
|
|
2008-11-19 08:37:26 +00:00
|
|
|
cairo_test_list_t **crashes_per_target;
|
2010-06-11 09:12:16 +01:00
|
|
|
cairo_test_list_t **errors_per_target;
|
2008-11-19 08:37:26 +00:00
|
|
|
cairo_test_list_t **fails_per_target;
|
|
|
|
|
|
|
|
|
|
int *num_failed_per_target;
|
2010-06-11 09:12:16 +01:00
|
|
|
int *num_error_per_target;
|
2008-11-19 08:37:26 +00:00
|
|
|
int *num_crashed_per_target;
|
|
|
|
|
|
|
|
|
|
cairo_bool_t foreground;
|
2009-08-25 07:16:16 +01:00
|
|
|
cairo_bool_t exit_on_failure;
|
2008-11-19 08:37:26 +00:00
|
|
|
cairo_bool_t list_only;
|
|
|
|
|
cairo_bool_t full_test;
|
2010-06-12 13:40:17 +01:00
|
|
|
cairo_bool_t keyword_match;
|
2010-06-12 13:48:12 +01:00
|
|
|
cairo_bool_t slow;
|
2010-05-07 21:30:13 +01:00
|
|
|
cairo_bool_t force_pass;
|
2008-11-19 08:37:26 +00:00
|
|
|
} cairo_test_runner_t;
|
|
|
|
|
|
2008-09-03 16:38:03 +01:00
|
|
|
typedef enum {
|
|
|
|
|
GE,
|
|
|
|
|
GT
|
|
|
|
|
} cairo_test_compare_op_t;
|
|
|
|
|
|
2011-10-28 15:04:59 +02:00
|
|
|
static cairo_test_list_t *tests;
|
2008-09-03 16:38:03 +01:00
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2009-08-22 17:53:59 +01:00
|
|
|
static cairo_bool_t
|
|
|
|
|
is_running_under_debugger (void)
|
|
|
|
|
{
|
2011-03-17 09:24:55 +01:00
|
|
|
#if HAVE_UNISTD_H && HAVE_LIBGEN_H && __linux__
|
2020-08-30 18:29:05 -06:00
|
|
|
char buf[1024] = { 0 };
|
|
|
|
|
char buf2[1024] = { 0 };
|
2009-08-22 17:53:59 +01:00
|
|
|
|
|
|
|
|
sprintf (buf, "/proc/%d/exe", getppid ());
|
2020-08-30 18:29:05 -06:00
|
|
|
if (readlink (buf, buf2, sizeof (buf2)) != -1 &&
|
|
|
|
|
buf2[1023] == 0 &&
|
|
|
|
|
strncmp (basename (buf2), "gdb", 3) == 0)
|
2009-08-22 17:53:59 +01:00
|
|
|
{
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2011-03-17 09:24:55 +01:00
|
|
|
if (RUNNING_ON_VALGRIND)
|
|
|
|
|
return TRUE;
|
|
|
|
|
|
2009-08-22 17:53:59 +01:00
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
2008-12-18 18:01:52 -05:00
|
|
|
#if SHOULD_FORK
|
2008-09-03 16:38:03 +01:00
|
|
|
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
|
2008-11-19 08:37:26 +00:00
|
|
|
_cairo_test_runner_preamble (cairo_test_runner_t *runner,
|
|
|
|
|
cairo_test_context_t *ctx)
|
2008-09-03 16:38:03 +01:00
|
|
|
{
|
2008-12-18 18:01:52 -05:00
|
|
|
#if SHOULD_FORK
|
2008-11-19 08:37:26 +00:00
|
|
|
if (! runner->foreground) {
|
|
|
|
|
pid_t pid;
|
2008-09-03 16:38:03 +01:00
|
|
|
|
2021-03-08 13:28:41 +01:00
|
|
|
/* fork() duplicates output buffers, so clear them */
|
|
|
|
|
fflush (NULL);
|
|
|
|
|
|
2008-11-19 08:37:26 +00:00
|
|
|
switch ((pid = fork ())) {
|
|
|
|
|
case -1: /* error */
|
|
|
|
|
return CAIRO_TEST_UNTESTED;
|
2008-09-03 16:38:03 +01:00
|
|
|
|
2008-11-19 08:37:26 +00:00
|
|
|
case 0: /* child */
|
|
|
|
|
exit (ctx->test->preamble (ctx));
|
2008-09-03 16:38:03 +01:00
|
|
|
|
2008-11-19 08:37:26 +00:00
|
|
|
default:
|
|
|
|
|
return _cairo_test_wait (pid);
|
|
|
|
|
}
|
2008-09-03 16:38:03 +01:00
|
|
|
}
|
|
|
|
|
#endif
|
2008-11-19 08:37:26 +00:00
|
|
|
return ctx->test->preamble (ctx);
|
2008-09-03 16:38:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static cairo_test_status_t
|
2008-11-19 08:37:26 +00:00
|
|
|
_cairo_test_runner_draw (cairo_test_runner_t *runner,
|
|
|
|
|
cairo_test_context_t *ctx,
|
2008-09-03 16:38:03 +01:00
|
|
|
const cairo_boilerplate_target_t *target,
|
|
|
|
|
cairo_bool_t similar,
|
2013-06-03 15:38:22 +02:00
|
|
|
int device_offset, int device_scale)
|
2008-09-03 16:38:03 +01:00
|
|
|
{
|
2008-12-18 18:01:52 -05:00
|
|
|
#if SHOULD_FORK
|
2008-11-19 08:37:26 +00:00
|
|
|
if (! runner->foreground) {
|
|
|
|
|
pid_t pid;
|
2008-09-03 16:38:03 +01:00
|
|
|
|
2021-03-08 13:28:41 +01:00
|
|
|
/* fork() duplicates output buffers, so clear them */
|
|
|
|
|
fflush (NULL);
|
|
|
|
|
|
2008-11-19 08:37:26 +00:00
|
|
|
switch ((pid = fork ())) {
|
|
|
|
|
case -1: /* error */
|
|
|
|
|
return CAIRO_TEST_UNTESTED;
|
2008-09-03 16:38:03 +01:00
|
|
|
|
2008-11-19 08:37:26 +00:00
|
|
|
case 0: /* child */
|
|
|
|
|
exit (_cairo_test_context_run_for_target (ctx, target,
|
2013-06-03 15:38:22 +02:00
|
|
|
similar, device_offset, device_scale));
|
2008-09-03 16:38:03 +01:00
|
|
|
|
2008-11-19 08:37:26 +00:00
|
|
|
default:
|
|
|
|
|
return _cairo_test_wait (pid);
|
|
|
|
|
}
|
2008-09-03 16:38:03 +01:00
|
|
|
}
|
2008-11-19 08:37:26 +00:00
|
|
|
#endif
|
2008-09-03 16:38:03 +01:00
|
|
|
return _cairo_test_context_run_for_target (ctx, target,
|
2013-06-03 15:38:22 +02:00
|
|
|
similar, device_offset, device_scale);
|
2008-09-03 16:38:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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;
|
2011-09-09 14:14:48 -03:00
|
|
|
int args_to_add = 0;
|
2008-09-03 16:38:03 +01:00
|
|
|
|
|
|
|
|
if (str == NULL)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
old_argc = *argc;
|
|
|
|
|
old_argv = *argv;
|
|
|
|
|
|
|
|
|
|
doit = FALSE;
|
|
|
|
|
do {
|
|
|
|
|
if (doit)
|
2011-09-09 14:14:48 -03:00
|
|
|
*argv = xmalloc (olen);
|
2008-09-03 16:38:03 +01:00
|
|
|
|
2011-09-09 14:14:48 -03:00
|
|
|
olen = sizeof (char *) * (args_to_add + *argc);
|
2008-09-03 16:38:03 +01:00
|
|
|
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';
|
2011-09-09 14:14:48 -03:00
|
|
|
} else {
|
|
|
|
|
olen += sizeof (char *);
|
2008-09-03 16:38:03 +01:00
|
|
|
}
|
2011-09-09 14:14:48 -03:00
|
|
|
args_to_add++;
|
2008-09-03 16:38:03 +01:00
|
|
|
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);
|
2011-09-09 14:14:48 -03:00
|
|
|
} else {
|
|
|
|
|
olen += sizeof (char *);
|
2008-09-03 16:38:03 +01:00
|
|
|
}
|
2011-09-09 14:14:48 -03:00
|
|
|
args_to_add++;
|
2008-09-03 16:38:03 +01:00
|
|
|
olen += len;
|
|
|
|
|
i++;
|
|
|
|
|
}
|
|
|
|
|
} while (doit++ == FALSE);
|
2011-09-09 14:14:48 -03:00
|
|
|
*argc = i;
|
2008-09-03 16:38:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
usage (const char *argv0)
|
|
|
|
|
{
|
|
|
|
|
fprintf (stderr,
|
2010-06-12 13:48:12 +01:00
|
|
|
"Usage: %s [-afkxsl] [test-names|keywords ...]\n"
|
2008-09-03 16:38:03 +01:00
|
|
|
"\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"
|
2008-11-19 08:37:26 +00:00
|
|
|
" -a all; run the full set of tests. By default the test suite\n"
|
2008-09-03 16:38:03 +01:00
|
|
|
" skips similar surface and device offset testing.\n"
|
2008-11-19 08:37:26 +00:00
|
|
|
" -f foreground; do not fork\n"
|
2010-06-12 13:40:17 +01:00
|
|
|
" -k match tests by keyword\n"
|
2011-10-02 16:50:37 -07:00
|
|
|
" -l list only; just list selected test case names without executing\n"
|
2010-06-12 13:48:12 +01:00
|
|
|
" -s include slow, long running tests\n"
|
2009-08-25 07:16:16 +01:00
|
|
|
" -x exit on first failure\n"
|
2008-09-03 16:38:03 +01:00
|
|
|
"\n"
|
2010-02-17 12:37:07 -08:00
|
|
|
"If test names are given they are used as matches either to a specific\n"
|
2008-09-03 16:38:03 +01:00
|
|
|
"test case or to a keyword, so a command such as\n"
|
2011-10-02 16:50:37 -07:00
|
|
|
"\"%s -k text\" can be used to run all text test cases, and\n"
|
|
|
|
|
"\"%s text-transform\" to run the individual case.\n",
|
|
|
|
|
argv0, argv0, argv0);
|
2008-09-03 16:38:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
_parse_cmdline (cairo_test_runner_t *runner, int *argc, char **argv[])
|
|
|
|
|
{
|
|
|
|
|
int c;
|
|
|
|
|
|
|
|
|
|
while (1) {
|
2011-10-02 16:15:59 -07:00
|
|
|
c = _cairo_getopt (*argc, *argv, ":afklsx");
|
2008-09-03 16:38:03 +01:00
|
|
|
if (c == -1)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
switch (c) {
|
2008-11-19 08:37:26 +00:00
|
|
|
case 'a':
|
2013-06-03 15:20:05 +01:00
|
|
|
runner->full_test = ~0;
|
2008-11-19 08:37:26 +00:00
|
|
|
break;
|
2011-10-02 16:15:59 -07:00
|
|
|
case 'f':
|
|
|
|
|
runner->foreground = TRUE;
|
|
|
|
|
break;
|
|
|
|
|
case 'k':
|
|
|
|
|
runner->keyword_match = TRUE;
|
2010-06-12 13:48:12 +01:00
|
|
|
break;
|
2008-09-03 16:38:03 +01:00
|
|
|
case 'l':
|
|
|
|
|
runner->list_only = TRUE;
|
|
|
|
|
break;
|
2011-10-02 16:15:59 -07:00
|
|
|
case 's':
|
|
|
|
|
runner->slow = TRUE;
|
2008-09-03 16:38:03 +01:00
|
|
|
break;
|
2009-08-25 07:16:16 +01:00
|
|
|
case 'x':
|
|
|
|
|
runner->exit_on_failure = TRUE;
|
|
|
|
|
break;
|
2008-09-03 16:38:03 +01:00
|
|
|
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)
|
|
|
|
|
{
|
2011-09-15 14:07:00 +01:00
|
|
|
cairo_test_init (&runner->base, "cairo-test-suite", ".");
|
2008-09-03 16:38:03 +01:00
|
|
|
|
2009-05-09 19:01:06 +01:00
|
|
|
runner->passed = TRUE;
|
|
|
|
|
|
2009-07-20 13:44:48 +01:00
|
|
|
runner->fails_preamble = NULL;
|
|
|
|
|
runner->crashes_preamble = NULL;
|
2010-06-11 09:12:16 +01:00
|
|
|
runner->errors_preamble = NULL;
|
2009-07-20 13:44:48 +01:00
|
|
|
|
2008-09-03 16:38:03 +01:00
|
|
|
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);
|
2010-06-11 09:12:16 +01:00
|
|
|
runner->errors_per_target = xcalloc (sizeof (cairo_test_list_t *),
|
|
|
|
|
runner->base.num_targets);
|
2008-09-03 16:38:03 +01:00
|
|
|
runner->num_failed_per_target = xcalloc (sizeof (int),
|
|
|
|
|
runner->base.num_targets);
|
2010-06-11 09:12:16 +01:00
|
|
|
runner->num_error_per_target = xcalloc (sizeof (int),
|
|
|
|
|
runner->base.num_targets);
|
2008-09-03 16:38:03 +01:00
|
|
|
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,
|
2009-07-13 14:31:43 +01:00
|
|
|
"%d Passed, %d Failed [%d crashed, %d expected], %d Skipped\n",
|
|
|
|
|
runner->num_passed,
|
2008-09-03 16:38:03 +01:00
|
|
|
|
|
|
|
|
runner->num_failed + runner->num_crashed + runner->num_xfailed,
|
|
|
|
|
runner->num_crashed,
|
|
|
|
|
runner->num_xfailed,
|
|
|
|
|
|
|
|
|
|
runner->num_skipped);
|
2021-04-17 10:01:17 +00:00
|
|
|
if (runner->num_ignored_via_env) {
|
|
|
|
|
_log (&runner->base,
|
|
|
|
|
"%d expected failure due to special request via environment variables!\n",
|
|
|
|
|
runner->num_ignored_via_env);
|
|
|
|
|
}
|
2008-09-03 16:38:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
_runner_print_details (cairo_test_runner_t *runner)
|
|
|
|
|
{
|
2009-07-20 13:44:48 +01:00
|
|
|
cairo_test_list_t *list;
|
2008-09-03 16:38:03 +01:00
|
|
|
unsigned int n;
|
|
|
|
|
|
2009-07-20 13:44:48 +01:00
|
|
|
if (runner->crashes_preamble) {
|
|
|
|
|
int count = 0;
|
|
|
|
|
|
|
|
|
|
for (list = runner->crashes_preamble; list != NULL; list = list->next)
|
|
|
|
|
count++;
|
|
|
|
|
|
|
|
|
|
_log (&runner->base, "Preamble: %d crashed! -", count);
|
|
|
|
|
|
|
|
|
|
for (list = runner->crashes_preamble; list != NULL; list = list->next) {
|
|
|
|
|
char *name = cairo_test_get_name (list->test);
|
|
|
|
|
_log (&runner->base, " %s", name);
|
|
|
|
|
free (name);
|
|
|
|
|
}
|
|
|
|
|
_log (&runner->base, "\n");
|
|
|
|
|
}
|
2010-06-11 09:12:16 +01:00
|
|
|
if (runner->errors_preamble) {
|
|
|
|
|
int count = 0;
|
|
|
|
|
|
|
|
|
|
for (list = runner->errors_preamble; list != NULL; list = list->next)
|
|
|
|
|
count++;
|
|
|
|
|
|
|
|
|
|
_log (&runner->base, "Preamble: %d error -", count);
|
|
|
|
|
|
|
|
|
|
for (list = runner->errors_preamble; list != NULL; list = list->next) {
|
|
|
|
|
char *name = cairo_test_get_name (list->test);
|
|
|
|
|
_log (&runner->base, " %s", name);
|
|
|
|
|
free (name);
|
|
|
|
|
}
|
|
|
|
|
_log (&runner->base, "\n");
|
|
|
|
|
}
|
2009-07-20 13:44:48 +01:00
|
|
|
if (runner->fails_preamble) {
|
|
|
|
|
int count = 0;
|
|
|
|
|
|
|
|
|
|
for (list = runner->fails_preamble; list != NULL; list = list->next)
|
|
|
|
|
count++;
|
|
|
|
|
|
|
|
|
|
_log (&runner->base, "Preamble: %d failed -", count);
|
|
|
|
|
|
|
|
|
|
for (list = runner->fails_preamble; list != NULL; list = list->next) {
|
|
|
|
|
char *name = cairo_test_get_name (list->test);
|
|
|
|
|
_log (&runner->base, " %s", name);
|
|
|
|
|
free (name);
|
|
|
|
|
}
|
|
|
|
|
_log (&runner->base, "\n");
|
|
|
|
|
}
|
|
|
|
|
|
2008-09-03 16:38:03 +01:00
|
|
|
for (n = 0; n < runner->base.num_targets; n++) {
|
|
|
|
|
const cairo_boilerplate_target_t *target;
|
|
|
|
|
|
|
|
|
|
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");
|
|
|
|
|
}
|
2010-06-11 09:12:16 +01:00
|
|
|
if (runner->num_error_per_target[n]) {
|
|
|
|
|
_log (&runner->base, "%s (%s): %d error -",
|
|
|
|
|
target->name,
|
|
|
|
|
cairo_boilerplate_content_name (target->content),
|
|
|
|
|
runner->num_error_per_target[n]);
|
|
|
|
|
|
|
|
|
|
for (list = runner->errors_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");
|
|
|
|
|
}
|
2008-09-03 16:38:03 +01:00
|
|
|
|
|
|
|
|
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");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
_runner_print_results (cairo_test_runner_t *runner)
|
|
|
|
|
{
|
|
|
|
|
_runner_print_summary (runner);
|
|
|
|
|
_runner_print_details (runner);
|
2009-05-09 19:01:06 +01:00
|
|
|
|
2009-06-13 12:19:51 +01:00
|
|
|
if (! runner->passed && ! runner->num_crashed) {
|
2009-05-09 19:01:06 +01:00
|
|
|
_log (&runner->base,
|
|
|
|
|
"\n"
|
|
|
|
|
"Note: These failures may be due to external factors.\n"
|
|
|
|
|
"Please read test/README -- \"Getting the elusive zero failures\".\n");
|
|
|
|
|
}
|
2008-09-03 16:38:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static cairo_test_status_t
|
|
|
|
|
_runner_fini (cairo_test_runner_t *runner)
|
|
|
|
|
{
|
|
|
|
|
unsigned int n;
|
|
|
|
|
|
2009-07-20 13:44:48 +01:00
|
|
|
_list_free (runner->crashes_preamble);
|
2010-06-11 09:12:16 +01:00
|
|
|
_list_free (runner->errors_preamble);
|
2009-07-20 13:44:48 +01:00
|
|
|
_list_free (runner->fails_preamble);
|
|
|
|
|
|
2008-09-03 16:38:03 +01:00
|
|
|
for (n = 0; n < runner->base.num_targets; n++) {
|
|
|
|
|
_list_free (runner->crashes_per_target[n]);
|
2010-06-11 09:12:16 +01:00
|
|
|
_list_free (runner->errors_per_target[n]);
|
2008-09-03 16:38:03 +01:00
|
|
|
_list_free (runner->fails_per_target[n]);
|
|
|
|
|
}
|
|
|
|
|
free (runner->crashes_per_target);
|
2010-06-11 09:12:16 +01:00
|
|
|
free (runner->errors_per_target);
|
2008-09-03 16:38:03 +01:00
|
|
|
free (runner->fails_per_target);
|
|
|
|
|
|
|
|
|
|
free (runner->num_crashed_per_target);
|
2010-06-11 09:12:16 +01:00
|
|
|
free (runner->num_error_per_target);
|
2008-09-03 16:38:03 +01:00
|
|
|
free (runner->num_failed_per_target);
|
|
|
|
|
|
|
|
|
|
cairo_test_fini (&runner->base);
|
|
|
|
|
|
2010-05-07 21:30:13 +01:00
|
|
|
if (runner->force_pass)
|
|
|
|
|
return CAIRO_TEST_SUCCESS;
|
|
|
|
|
|
2008-09-03 16:38:03 +01:00
|
|
|
return runner->num_failed + runner->num_crashed ?
|
|
|
|
|
CAIRO_TEST_FAILURE :
|
2009-07-13 14:31:43 +01:00
|
|
|
runner->num_passed + runner->num_xfailed ?
|
2008-09-03 16:38:03 +01:00
|
|
|
CAIRO_TEST_SUCCESS : CAIRO_TEST_UNTESTED;
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-17 10:01:17 +00:00
|
|
|
static cairo_bool_t
|
|
|
|
|
expect_fail_due_to_env_var (cairo_test_context_t *ctx,
|
|
|
|
|
const cairo_boilerplate_target_t *target)
|
|
|
|
|
{
|
|
|
|
|
const char *prefix = "CAIRO_TEST_IGNORE_";
|
|
|
|
|
const char *content = cairo_boilerplate_content_name (target->content);
|
|
|
|
|
char *env_name;
|
|
|
|
|
const char *env;
|
|
|
|
|
cairo_bool_t result = FALSE;
|
2021-04-25 11:05:59 +02:00
|
|
|
char *to_replace;
|
2021-04-17 10:01:17 +00:00
|
|
|
|
|
|
|
|
/* Construct the name of the env var */
|
|
|
|
|
env_name = malloc (strlen (prefix) + strlen (target->name) + 1 + strlen (content) + 1);
|
|
|
|
|
if (env_name == NULL) {
|
|
|
|
|
fprintf(stderr, "Malloc failed, cannot check $%s%s_%s\n", prefix, target->name, content);
|
|
|
|
|
cairo_test_log(ctx, "Malloc failed, cannot check $%s%s_%s\n", prefix, target->name, content);
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
strcpy (env_name, prefix);
|
|
|
|
|
strcat (env_name, target->name);
|
|
|
|
|
strcat (env_name, "_");
|
|
|
|
|
strcat (env_name, content);
|
|
|
|
|
|
2021-04-25 11:05:59 +02:00
|
|
|
/* Deal with some invalid characters: Replace '-' and '&' with '_' */
|
|
|
|
|
while ((to_replace = strchr(env_name, '-')) != NULL) {
|
|
|
|
|
*to_replace = '_';
|
|
|
|
|
}
|
|
|
|
|
while ((to_replace = strchr(env_name, '&')) != NULL) {
|
|
|
|
|
*to_replace = '_';
|
|
|
|
|
}
|
|
|
|
|
|
2021-04-17 10:01:17 +00:00
|
|
|
env = getenv (env_name);
|
|
|
|
|
|
|
|
|
|
/* Look for the test name in the env var (comma separated) */
|
|
|
|
|
if (env) {
|
2021-05-03 23:41:41 +02:00
|
|
|
for (size_t start = 0;; start += strlen (ctx->test_name)) {
|
|
|
|
|
char *match = strstr (env + start, ctx->test_name);
|
2021-04-17 10:01:17 +00:00
|
|
|
if (!match)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
/* Make sure that "foo" does not match in "barfoo,foobaz"
|
|
|
|
|
* There must be commas around the test name (or string begin/end)
|
|
|
|
|
*/
|
|
|
|
|
if (env == match || match[-1] == ',') {
|
|
|
|
|
char *end = match + strlen (ctx->test_name);
|
|
|
|
|
if (*end == '\0' || *end == ',') {
|
|
|
|
|
result = TRUE;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (result)
|
|
|
|
|
cairo_test_log (ctx,
|
|
|
|
|
"Expecting '%s' to fail because it appears in $%s\n",
|
|
|
|
|
ctx->test_name, env_name);
|
|
|
|
|
|
|
|
|
|
free (env_name);
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2008-09-03 16:38:03 +01:00
|
|
|
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, µ))
|
|
|
|
|
{
|
|
|
|
|
fprintf (stderr, "unrecognised cairo version requirement '%s'\n", str);
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return _version_compare (cairo_version (),
|
|
|
|
|
op,
|
|
|
|
|
CAIRO_VERSION_ENCODE (major, minor, micro));
|
|
|
|
|
}
|
|
|
|
|
|
2013-06-03 15:20:05 +01:00
|
|
|
#define TEST_SIMILAR 0x1
|
|
|
|
|
#define TEST_OFFSET 0x2
|
|
|
|
|
#define TEST_SCALE 0x4
|
2008-09-03 16:38:03 +01:00
|
|
|
int
|
|
|
|
|
main (int argc, char **argv)
|
|
|
|
|
{
|
|
|
|
|
cairo_test_runner_t runner;
|
2011-10-28 15:04:59 +02:00
|
|
|
cairo_test_list_t *test_list;
|
2008-09-03 16:38:03 +01:00
|
|
|
cairo_test_status_t *target_status;
|
2013-06-03 15:38:22 +02:00
|
|
|
unsigned int n, m, k;
|
2008-09-03 16:38:03 +01:00
|
|
|
char targets[4096];
|
|
|
|
|
int len;
|
2011-09-09 14:17:39 -03:00
|
|
|
char *cairo_tests_env;
|
2008-09-03 16:38:03 +01:00
|
|
|
|
|
|
|
|
#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
|
|
|
|
|
|
|
|
|
|
_cairo_test_runner_register_tests ();
|
2011-10-28 15:04:59 +02:00
|
|
|
tests = _list_reverse (tests);
|
2008-09-03 16:38:03 +01:00
|
|
|
|
|
|
|
|
memset (&runner, 0, sizeof (runner));
|
|
|
|
|
runner.num_device_offsets = 1;
|
2013-06-03 15:38:22 +02:00
|
|
|
runner.num_device_scales = 1;
|
2008-09-03 16:38:03 +01:00
|
|
|
|
2009-08-22 17:53:59 +01:00
|
|
|
if (is_running_under_debugger ())
|
|
|
|
|
runner.foreground = TRUE;
|
|
|
|
|
|
2008-09-03 16:38:03 +01:00
|
|
|
if (getenv ("CAIRO_TEST_MODE")) {
|
|
|
|
|
const char *env = getenv ("CAIRO_TEST_MODE");
|
|
|
|
|
|
|
|
|
|
if (strstr (env, "full")) {
|
2013-06-03 15:20:05 +01:00
|
|
|
runner.full_test = ~0;
|
|
|
|
|
}
|
|
|
|
|
if (strstr (env, "similar")) {
|
|
|
|
|
runner.full_test |= TEST_SIMILAR;
|
|
|
|
|
}
|
|
|
|
|
if (strstr (env, "offset")) {
|
|
|
|
|
runner.full_test |= TEST_OFFSET;
|
|
|
|
|
}
|
|
|
|
|
if (strstr (env, "scale")) {
|
|
|
|
|
runner.full_test |= TEST_SCALE;
|
2008-09-03 16:38:03 +01:00
|
|
|
}
|
2008-11-19 08:37:26 +00:00
|
|
|
if (strstr (env, "foreground")) {
|
|
|
|
|
runner.foreground = TRUE;
|
|
|
|
|
}
|
2009-08-25 07:16:16 +01:00
|
|
|
if (strstr (env, "exit-on-failure")) {
|
|
|
|
|
runner.exit_on_failure = TRUE;
|
|
|
|
|
}
|
2008-09-03 16:38:03 +01:00
|
|
|
}
|
|
|
|
|
|
2010-05-07 21:30:13 +01:00
|
|
|
if (getenv ("CAIRO_TEST_FORCE_PASS")) {
|
|
|
|
|
const char *env = getenv ("CAIRO_TEST_FORCE_PASS");
|
|
|
|
|
|
|
|
|
|
runner.force_pass = atoi (env);
|
|
|
|
|
}
|
|
|
|
|
|
2008-09-03 16:38:03 +01:00
|
|
|
_parse_cmdline (&runner, &argc, &argv);
|
2011-09-09 14:17:39 -03:00
|
|
|
|
|
|
|
|
cairo_tests_env = getenv("CAIRO_TESTS");
|
|
|
|
|
append_argv (&argc, &argv, cairo_tests_env);
|
2008-09-03 16:38:03 +01:00
|
|
|
|
2013-06-03 15:20:05 +01:00
|
|
|
if (runner.full_test & TEST_OFFSET) {
|
2008-09-03 16:38:03 +01:00
|
|
|
runner.num_device_offsets = 2;
|
2013-06-03 15:20:05 +01:00
|
|
|
}
|
|
|
|
|
if (runner.full_test & TEST_SCALE) {
|
2013-06-03 15:38:22 +02:00
|
|
|
runner.num_device_scales = 2;
|
2008-09-03 16:38:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
2011-10-28 15:04:59 +02:00
|
|
|
for (test_list = tests; test_list != NULL; test_list = test_list->next) {
|
|
|
|
|
const cairo_test_t *test = test_list->test;
|
2008-09-03 16:38:03 +01:00
|
|
|
cairo_test_context_t ctx;
|
2009-07-13 14:31:43 +01:00
|
|
|
cairo_test_status_t status;
|
2010-06-11 09:12:16 +01:00
|
|
|
cairo_bool_t failed = FALSE, xfailed = FALSE, error = FALSE, crashed = FALSE, skipped = TRUE;
|
2009-07-20 13:44:48 +01:00
|
|
|
cairo_bool_t in_preamble = FALSE;
|
2010-05-03 20:39:34 +01:00
|
|
|
char *name = cairo_test_get_name (test);
|
2008-09-03 16:38:03 +01:00
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
/* check for restricted runs */
|
|
|
|
|
if (argc) {
|
|
|
|
|
cairo_bool_t found = FALSE;
|
2010-05-03 20:39:34 +01:00
|
|
|
const char *keywords = test->keywords;
|
2008-09-03 16:38:03 +01:00
|
|
|
|
|
|
|
|
for (i = 0; i < argc; i++) {
|
|
|
|
|
const char *match = argv[i];
|
|
|
|
|
cairo_bool_t invert = match[0] == '!';
|
|
|
|
|
if (invert)
|
|
|
|
|
match++;
|
|
|
|
|
|
2010-06-12 13:40:17 +01:00
|
|
|
if (runner.keyword_match) {
|
|
|
|
|
if (keywords != NULL && strstr (keywords, match) != NULL) {
|
|
|
|
|
found = ! invert;
|
|
|
|
|
break;
|
|
|
|
|
} else if (invert) {
|
|
|
|
|
found = TRUE;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
/* exact match on test name */
|
|
|
|
|
if (strcmp (name, match) == 0) {
|
|
|
|
|
found = ! invert;
|
|
|
|
|
break;
|
|
|
|
|
} else if (invert) {
|
|
|
|
|
found = TRUE;
|
|
|
|
|
}
|
2008-09-03 16:38:03 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (! found) {
|
|
|
|
|
free (name);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* check to see if external requirements match */
|
2010-05-03 20:39:34 +01:00
|
|
|
if (test->requirements != NULL) {
|
|
|
|
|
const char *requirements = test->requirements;
|
2008-09-03 16:38:03 +01:00
|
|
|
const char *str;
|
|
|
|
|
|
2010-06-12 13:48:12 +01:00
|
|
|
str = strstr (requirements, "slow");
|
|
|
|
|
if (str != NULL && ! runner.slow) {
|
|
|
|
|
if (runner.list_only)
|
|
|
|
|
goto TEST_NEXT;
|
|
|
|
|
else
|
|
|
|
|
goto TEST_SKIPPED;
|
|
|
|
|
}
|
|
|
|
|
|
2008-09-03 16:38:03 +01:00
|
|
|
str = strstr (requirements, "cairo");
|
|
|
|
|
if (str != NULL && ! _has_required_cairo_version (str)) {
|
|
|
|
|
if (runner.list_only)
|
|
|
|
|
goto TEST_NEXT;
|
|
|
|
|
else
|
|
|
|
|
goto TEST_SKIPPED;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (runner.list_only) {
|
|
|
|
|
printf ("%s ", name);
|
|
|
|
|
goto TEST_NEXT;
|
|
|
|
|
}
|
|
|
|
|
|
2010-05-03 20:39:34 +01:00
|
|
|
_cairo_test_context_init_for_test (&ctx, &runner.base, test);
|
2008-09-03 16:38:03 +01:00
|
|
|
memset (target_status, 0,
|
|
|
|
|
sizeof (cairo_test_status_t) * ctx.num_targets);
|
|
|
|
|
|
|
|
|
|
if (ctx.test->preamble != NULL) {
|
2008-11-19 08:37:26 +00:00
|
|
|
status = _cairo_test_runner_preamble (&runner, &ctx);
|
2021-08-15 18:12:04 +02:00
|
|
|
if (getenv ("CAIRO_TEST_UGLY_HACK_TO_IGNORE_PS_FAILURES")) {
|
2023-04-29 11:15:54 +09:30
|
|
|
if (strcmp (ctx.test_name, "ps-eps") == 0) {
|
2021-08-15 18:12:04 +02:00
|
|
|
if (status == CAIRO_TEST_FAILURE) {
|
|
|
|
|
cairo_test_log (&ctx, "Turning FAIL into XFAIL due to env\n");
|
|
|
|
|
fprintf (stderr, "Turning FAIL into XFAIL due to env\n");
|
|
|
|
|
runner.num_ignored_via_env++;
|
|
|
|
|
status = CAIRO_TEST_XFAILURE;
|
|
|
|
|
} else {
|
|
|
|
|
fprintf (stderr, "Test was expected to fail due to an environment variable, but did not!\n");
|
|
|
|
|
fprintf (stderr, "Please update the corresponding CAIRO_TEST_IGNORE_* variable.\n");
|
|
|
|
|
status = CAIRO_TEST_ERROR;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2008-09-03 16:38:03 +01:00
|
|
|
switch (status) {
|
|
|
|
|
case CAIRO_TEST_SUCCESS:
|
2009-07-20 13:44:48 +01:00
|
|
|
in_preamble = TRUE;
|
2008-09-03 16:38:03 +01:00
|
|
|
skipped = FALSE;
|
|
|
|
|
break;
|
2009-07-20 13:44:48 +01:00
|
|
|
|
2009-07-13 14:31:43 +01:00
|
|
|
case CAIRO_TEST_XFAILURE:
|
2009-07-20 13:44:48 +01:00
|
|
|
in_preamble = TRUE;
|
2009-07-13 14:31:43 +01:00
|
|
|
xfailed = TRUE;
|
|
|
|
|
goto TEST_DONE;
|
2009-07-20 13:44:48 +01:00
|
|
|
|
2009-07-13 14:31:43 +01:00
|
|
|
case CAIRO_TEST_NEW:
|
2008-09-03 16:38:03 +01:00
|
|
|
case CAIRO_TEST_FAILURE:
|
2009-07-20 13:44:48 +01:00
|
|
|
runner.fails_preamble = _list_prepend (runner.fails_preamble,
|
2010-05-03 20:39:34 +01:00
|
|
|
test);
|
2009-07-20 13:44:48 +01:00
|
|
|
in_preamble = TRUE;
|
2008-09-03 16:38:03 +01:00
|
|
|
failed = TRUE;
|
|
|
|
|
goto TEST_DONE;
|
2009-07-20 13:44:48 +01:00
|
|
|
|
2010-06-11 09:12:16 +01:00
|
|
|
case CAIRO_TEST_ERROR:
|
|
|
|
|
runner.errors_preamble = _list_prepend (runner.errors_preamble,
|
|
|
|
|
test);
|
|
|
|
|
in_preamble = TRUE;
|
|
|
|
|
failed = TRUE;
|
|
|
|
|
goto TEST_DONE;
|
|
|
|
|
|
2009-07-13 14:31:43 +01:00
|
|
|
case CAIRO_TEST_NO_MEMORY:
|
2008-09-03 16:38:03 +01:00
|
|
|
case CAIRO_TEST_CRASHED:
|
2009-07-20 13:44:48 +01:00
|
|
|
runner.crashes_preamble = _list_prepend (runner.crashes_preamble,
|
2010-05-03 20:39:34 +01:00
|
|
|
test);
|
2009-07-20 13:44:48 +01:00
|
|
|
in_preamble = TRUE;
|
2008-09-03 16:38:03 +01:00
|
|
|
failed = TRUE;
|
|
|
|
|
goto TEST_DONE;
|
2009-07-20 13:44:48 +01:00
|
|
|
|
2008-09-03 16:38:03 +01:00
|
|
|
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,
|
2009-07-13 14:31:43 +01:00
|
|
|
target_xfailed = FALSE,
|
2010-06-11 09:12:16 +01:00
|
|
|
target_error = FALSE,
|
2008-09-03 16:38:03 +01:00
|
|
|
target_crashed = FALSE,
|
|
|
|
|
target_skipped = TRUE;
|
2011-03-17 09:27:02 +01:00
|
|
|
cairo_test_similar_t has_similar;
|
2008-09-03 16:38:03 +01:00
|
|
|
|
|
|
|
|
target = ctx.targets_to_test[n];
|
|
|
|
|
|
2013-06-03 15:20:05 +01:00
|
|
|
has_similar = runner.full_test & TEST_SIMILAR ?
|
2008-09-03 16:38:03 +01:00
|
|
|
cairo_test_target_has_similar (&ctx, target) :
|
2011-03-17 09:27:02 +01:00
|
|
|
DIRECT;
|
2008-09-03 16:38:03 +01:00
|
|
|
for (m = 0; m < runner.num_device_offsets; m++) {
|
2013-06-03 15:38:22 +02:00
|
|
|
for (k = 0; k < runner.num_device_scales; k++) {
|
|
|
|
|
int dev_offset = m * 25;
|
|
|
|
|
int dev_scale = k + 1;
|
|
|
|
|
cairo_test_similar_t similar;
|
|
|
|
|
|
|
|
|
|
for (similar = DIRECT; similar <= has_similar; similar++) {
|
|
|
|
|
status = _cairo_test_runner_draw (&runner, &ctx, target,
|
|
|
|
|
similar, dev_offset, dev_scale);
|
2021-04-17 10:01:17 +00:00
|
|
|
|
|
|
|
|
if (expect_fail_due_to_env_var (&ctx, target)) {
|
|
|
|
|
if (status == CAIRO_TEST_FAILURE) {
|
|
|
|
|
cairo_test_log (&ctx, "Turning FAIL into XFAIL due to env\n");
|
|
|
|
|
fprintf (stderr, "Turning FAIL into XFAIL due to env\n");
|
|
|
|
|
runner.num_ignored_via_env++;
|
|
|
|
|
status = CAIRO_TEST_XFAILURE;
|
|
|
|
|
} else {
|
|
|
|
|
fprintf (stderr, "Test was expected to fail due to an environment variable, but did not!\n");
|
|
|
|
|
fprintf (stderr, "Please update the corresponding CAIRO_TEST_IGNORE_* variable.\n");
|
|
|
|
|
status = CAIRO_TEST_ERROR;
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-05-03 23:41:41 +02:00
|
|
|
if (getenv ("CAIRO_TEST_UGLY_HACK_TO_SOMETIMES_IGNORE_SCRIPT_XCB_HUGE_IMAGE_SHM")) {
|
2021-04-17 10:01:17 +00:00
|
|
|
if (strcmp (target->name, "script") == 0 && strcmp (ctx.test_name, "xcb-huge-image-shm") == 0) {
|
|
|
|
|
if (status == CAIRO_TEST_FAILURE) {
|
2021-05-03 23:41:41 +02:00
|
|
|
fprintf (stderr, "This time the xcb-huge-image-shm test on script surface failed.\n");
|
2021-04-17 10:01:17 +00:00
|
|
|
cairo_test_log (&ctx, "Turning FAIL into XFAIL due to env\n");
|
|
|
|
|
fprintf (stderr, "Turning FAIL into XFAIL due to env\n");
|
|
|
|
|
runner.num_ignored_via_env++;
|
2021-04-22 16:14:37 +02:00
|
|
|
} else {
|
2021-05-03 23:41:41 +02:00
|
|
|
fprintf (stderr, "This time the xcb-huge-image-shm test on script surface did not fail.\n");
|
|
|
|
|
cairo_test_log (&ctx, "Turning the status into XFAIL due to env\n");
|
|
|
|
|
fprintf (stderr, "Turning the status into XFAIL due to env\n");
|
2021-04-22 16:14:37 +02:00
|
|
|
}
|
2021-05-03 23:41:41 +02:00
|
|
|
status = CAIRO_TEST_XFAILURE;
|
|
|
|
|
fprintf (stderr, "If you are were getting one of the outcomes for some time, please update this code.\n");
|
2021-04-22 16:14:37 +02:00
|
|
|
}
|
|
|
|
|
}
|
2013-06-03 15:38:22 +02:00
|
|
|
switch (status) {
|
|
|
|
|
case CAIRO_TEST_SUCCESS:
|
|
|
|
|
target_skipped = FALSE;
|
|
|
|
|
break;
|
|
|
|
|
case CAIRO_TEST_XFAILURE:
|
|
|
|
|
target_xfailed = TRUE;
|
|
|
|
|
break;
|
|
|
|
|
case CAIRO_TEST_NEW:
|
|
|
|
|
case CAIRO_TEST_FAILURE:
|
|
|
|
|
target_failed = TRUE;
|
|
|
|
|
break;
|
|
|
|
|
case CAIRO_TEST_ERROR:
|
|
|
|
|
target_error = TRUE;
|
|
|
|
|
break;
|
|
|
|
|
case CAIRO_TEST_NO_MEMORY:
|
|
|
|
|
case CAIRO_TEST_CRASHED:
|
|
|
|
|
target_crashed = TRUE;
|
|
|
|
|
break;
|
|
|
|
|
case CAIRO_TEST_UNTESTED:
|
|
|
|
|
break;
|
|
|
|
|
}
|
2008-09-03 16:38:03 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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],
|
2010-05-03 20:39:34 +01:00
|
|
|
test);
|
2008-09-03 16:38:03 +01:00
|
|
|
crashed = TRUE;
|
2010-06-11 09:12:16 +01:00
|
|
|
} else if (target_error) {
|
|
|
|
|
target_status[n] = CAIRO_TEST_ERROR;
|
|
|
|
|
runner.num_error_per_target[n]++;
|
|
|
|
|
runner.errors_per_target[n] = _list_prepend (runner.errors_per_target[n],
|
|
|
|
|
test);
|
|
|
|
|
|
|
|
|
|
error = TRUE;
|
2008-09-03 16:38:03 +01:00
|
|
|
} else if (target_failed) {
|
2009-07-13 14:31:43 +01:00
|
|
|
target_status[n] = CAIRO_TEST_FAILURE;
|
|
|
|
|
runner.num_failed_per_target[n]++;
|
|
|
|
|
runner.fails_per_target[n] = _list_prepend (runner.fails_per_target[n],
|
2010-05-03 20:39:34 +01:00
|
|
|
test);
|
2008-09-03 16:38:03 +01:00
|
|
|
|
|
|
|
|
failed = TRUE;
|
2009-07-13 14:31:43 +01:00
|
|
|
} else if (target_xfailed) {
|
|
|
|
|
target_status[n] = CAIRO_TEST_XFAILURE;
|
|
|
|
|
xfailed = TRUE;
|
2008-09-03 16:38:03 +01:00
|
|
|
} else if (target_skipped) {
|
|
|
|
|
target_status[n] = CAIRO_TEST_UNTESTED;
|
|
|
|
|
} else {
|
|
|
|
|
target_status[n] = CAIRO_TEST_SUCCESS;
|
|
|
|
|
skipped = FALSE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_DONE:
|
|
|
|
|
cairo_test_fini (&ctx);
|
|
|
|
|
TEST_SKIPPED:
|
|
|
|
|
targets[0] = '\0';
|
|
|
|
|
if (crashed) {
|
2009-07-20 13:44:48 +01:00
|
|
|
if (! in_preamble) {
|
|
|
|
|
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);
|
|
|
|
|
}
|
2008-09-03 16:38:03 +01:00
|
|
|
}
|
|
|
|
|
}
|
2009-07-20 13:44:48 +01:00
|
|
|
targets[len-2] = '\0';
|
|
|
|
|
_log (&runner.base, "\n%s: CRASH! (%s)\n", name, targets);
|
|
|
|
|
} else {
|
|
|
|
|
_log (&runner.base, "\n%s: CRASH!\n", name);
|
2008-09-03 16:38:03 +01:00
|
|
|
}
|
|
|
|
|
runner.num_crashed++;
|
2009-05-09 19:01:06 +01:00
|
|
|
runner.passed = FALSE;
|
2010-06-11 09:12:16 +01:00
|
|
|
} else if (error) {
|
|
|
|
|
if (! in_preamble) {
|
|
|
|
|
len = 0;
|
|
|
|
|
for (n = 0 ; n < runner.base.num_targets; n++) {
|
|
|
|
|
if (target_status[n] == CAIRO_TEST_ERROR) {
|
|
|
|
|
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, "%s: ERROR (%s)\n", name, targets);
|
|
|
|
|
} else {
|
|
|
|
|
_log (&runner.base, "%s: ERROR\n", name);
|
|
|
|
|
}
|
|
|
|
|
runner.num_error++;
|
|
|
|
|
runner.passed = FALSE;
|
2008-09-03 16:38:03 +01:00
|
|
|
} else if (failed) {
|
2009-07-20 13:44:48 +01:00
|
|
|
if (! in_preamble) {
|
|
|
|
|
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);
|
|
|
|
|
}
|
2008-09-03 16:38:03 +01:00
|
|
|
}
|
|
|
|
|
}
|
2009-07-20 13:44:48 +01:00
|
|
|
targets[len-2] = '\0';
|
|
|
|
|
_log (&runner.base, "%s: FAIL (%s)\n", name, targets);
|
|
|
|
|
} else {
|
|
|
|
|
_log (&runner.base, "%s: FAIL\n", name);
|
2008-09-03 16:38:03 +01:00
|
|
|
}
|
2009-07-13 14:31:43 +01:00
|
|
|
runner.num_failed++;
|
|
|
|
|
runner.passed = FALSE;
|
|
|
|
|
} else if (xfailed) {
|
|
|
|
|
_log (&runner.base, "%s: XFAIL\n", name);
|
|
|
|
|
runner.num_xfailed++;
|
2008-09-03 16:38:03 +01:00
|
|
|
} else if (skipped) {
|
|
|
|
|
_log (&runner.base, "%s: UNTESTED\n", name);
|
|
|
|
|
runner.num_skipped++;
|
|
|
|
|
} else {
|
2009-07-13 14:31:43 +01:00
|
|
|
_log (&runner.base, "%s: PASS\n", name);
|
|
|
|
|
runner.num_passed++;
|
2008-09-03 16:38:03 +01:00
|
|
|
}
|
|
|
|
|
fflush (runner.base.log_file);
|
|
|
|
|
|
|
|
|
|
TEST_NEXT:
|
|
|
|
|
free (name);
|
2009-08-25 07:16:16 +01:00
|
|
|
if (runner.exit_on_failure && ! runner.passed)
|
|
|
|
|
break;
|
|
|
|
|
|
2008-09-03 16:38:03 +01:00
|
|
|
}
|
|
|
|
|
|
2011-09-09 14:17:39 -03:00
|
|
|
if (cairo_tests_env)
|
|
|
|
|
free(argv);
|
|
|
|
|
|
2008-09-03 16:38:03 +01:00
|
|
|
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]);
|
2010-06-11 09:12:16 +01:00
|
|
|
runner.errors_per_target[n] = _list_reverse (runner.errors_per_target[n]);
|
2008-09-03 16:38:03 +01:00
|
|
|
runner.fails_per_target[n] = _list_reverse (runner.fails_per_target[n]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_runner_print_results (&runner);
|
|
|
|
|
|
2014-11-20 17:22:30 +01:00
|
|
|
_list_free (tests);
|
2008-09-03 16:38:03 +01:00
|
|
|
free (target_status);
|
|
|
|
|
return _runner_fini (&runner);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
2010-05-03 20:39:34 +01:00
|
|
|
cairo_test_register (cairo_test_t *test)
|
2008-09-03 16:38:03 +01:00
|
|
|
{
|
2011-10-28 15:04:59 +02:00
|
|
|
tests = _list_prepend (tests, test);
|
2008-09-03 16:38:03 +01:00
|
|
|
}
|