1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/ossrv/glib/glib/gtester.c Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,711 @@
1.4 +/* GLib testing framework runner
1.5 + * Copyright (C) 2007 Sven Herzberg
1.6 + * Copyright (C) 2007 Tim Janik
1.7 + *
1.8 + * This library is free software; you can redistribute it and/or
1.9 + * modify it under the terms of the GNU Lesser General Public
1.10 + * License as published by the Free Software Foundation; either
1.11 + * version 2 of the License, or (at your option) any later version.
1.12 + *
1.13 + * This library is distributed in the hope that it will be useful,
1.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1.16 + * Lesser General Public License for more details.
1.17 + *
1.18 + * You should have received a copy of the GNU Lesser General Public
1.19 + * License along with this library; if not, write to the
1.20 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
1.21 + * Boston, MA 02111-1307, USA.
1.22 + */
1.23 +#include <glib.h>
1.24 +#include <gstdio.h>
1.25 +#include <string.h>
1.26 +#include <stdlib.h>
1.27 +#include <unistd.h>
1.28 +#include <fcntl.h>
1.29 +#include <sys/wait.h>
1.30 +#include <errno.h>
1.31 +#include <signal.h>
1.32 +
1.33 +/* the read buffer size in bytes */
1.34 +#define READ_BUFFER_SIZE 4096
1.35 +
1.36 +/* --- prototypes --- */
1.37 +static int main_selftest (int argc,
1.38 + char **argv);
1.39 +static void parse_args (gint *argc_p,
1.40 + gchar ***argv_p);
1.41 +
1.42 +/* --- variables --- */
1.43 +static GIOChannel *ioc_report = NULL;
1.44 +static gboolean gtester_quiet = FALSE;
1.45 +static gboolean gtester_verbose = FALSE;
1.46 +static gboolean gtester_list_tests = FALSE;
1.47 +static gboolean gtester_selftest = FALSE;
1.48 +static gboolean subtest_running = FALSE;
1.49 +static gint subtest_exitstatus = 0;
1.50 +static gboolean subtest_io_pending = FALSE;
1.51 +static gboolean subtest_quiet = TRUE;
1.52 +static gboolean subtest_verbose = FALSE;
1.53 +static gboolean subtest_mode_fatal = TRUE;
1.54 +static gboolean subtest_mode_perf = FALSE;
1.55 +static gboolean subtest_mode_quick = TRUE;
1.56 +static const gchar *subtest_seedstr = NULL;
1.57 +static gchar *subtest_last_seed = NULL;
1.58 +static GSList *subtest_paths = NULL;
1.59 +static GSList *subtest_args = NULL;
1.60 +static gboolean testcase_open = FALSE;
1.61 +static guint testcase_count = 0;
1.62 +static guint testcase_fail_count = 0;
1.63 +static const gchar *output_filename = NULL;
1.64 +static guint log_indent = 0;
1.65 +static gint log_fd = -1;
1.66 +
1.67 +/* --- functions --- */
1.68 +static const char*
1.69 +sindent (guint n)
1.70 +{
1.71 + static const char spaces[] = " ";
1.72 + int l = sizeof (spaces) - 1;
1.73 + n = MIN (n, l);
1.74 + return spaces + l - n;
1.75 +}
1.76 +
1.77 +static void G_GNUC_PRINTF (1, 2)
1.78 +test_log_printfe (const char *format,
1.79 + ...)
1.80 +{
1.81 + char *result;
1.82 + int r;
1.83 + va_list args;
1.84 + va_start (args, format);
1.85 + result = g_markup_vprintf_escaped (format, args);
1.86 + va_end (args);
1.87 + do
1.88 + r = write (log_fd, result, strlen (result));
1.89 + while (r < 0 && errno == EINTR);
1.90 + g_free (result);
1.91 +}
1.92 +
1.93 +static void
1.94 +terminate (void)
1.95 +{
1.96 + kill (getpid(), SIGTERM);
1.97 + abort();
1.98 +}
1.99 +
1.100 +static void
1.101 +testcase_close (long double duration,
1.102 + gint exit_status,
1.103 + guint n_forks)
1.104 +{
1.105 + g_return_if_fail (testcase_open > 0);
1.106 + test_log_printfe ("%s<duration>%.6Lf</duration>\n", sindent (log_indent), duration);
1.107 + test_log_printfe ("%s<status exit-status=\"%d\" n-forks=\"%d\" result=\"%s\"/>\n",
1.108 + sindent (log_indent), exit_status, n_forks,
1.109 + exit_status ? "failed" : "success");
1.110 + log_indent -= 2;
1.111 + test_log_printfe ("%s</testcase>\n", sindent (log_indent));
1.112 + testcase_open--;
1.113 + if (gtester_verbose)
1.114 + g_print ("%s\n", exit_status ? "FAIL" : "OK");
1.115 + if (exit_status && subtest_last_seed)
1.116 + g_print ("GTester: last random seed: %s\n", subtest_last_seed);
1.117 + if (exit_status)
1.118 + testcase_fail_count += 1;
1.119 + if (subtest_mode_fatal && testcase_fail_count)
1.120 + terminate();
1.121 +}
1.122 +
1.123 +static void
1.124 +test_log_msg (GTestLogMsg *msg)
1.125 +{
1.126 + switch (msg->log_type)
1.127 + {
1.128 + guint i;
1.129 + gchar **strv;
1.130 + case G_TEST_LOG_NONE:
1.131 + break;
1.132 + case G_TEST_LOG_ERROR:
1.133 + strv = g_strsplit (msg->strings[0], "\n", -1);
1.134 + for (i = 0; strv[i]; i++)
1.135 + test_log_printfe ("%s<error>%s</error>\n", sindent (log_indent), strv[i]);
1.136 + g_strfreev (strv);
1.137 + break;
1.138 + case G_TEST_LOG_START_BINARY:
1.139 + test_log_printfe ("%s<binary file=\"%s\"/>\n", sindent (log_indent), msg->strings[0]);
1.140 + subtest_last_seed = g_strdup (msg->strings[1]);
1.141 + test_log_printfe ("%s<random-seed>%s</random-seed>\n", sindent (log_indent), subtest_last_seed);
1.142 + break;
1.143 + case G_TEST_LOG_LIST_CASE:
1.144 + g_print ("%s\n", msg->strings[0]);
1.145 + break;
1.146 + case G_TEST_LOG_START_CASE:
1.147 + testcase_count++;
1.148 + if (gtester_verbose)
1.149 + {
1.150 + gchar *sc = g_strconcat (msg->strings[0], ":", NULL);
1.151 + gchar *sleft = g_strdup_printf ("%-68s", sc);
1.152 + g_free (sc);
1.153 + g_print ("%70s ", sleft);
1.154 + g_free (sleft);
1.155 + }
1.156 + g_return_if_fail (testcase_open == 0);
1.157 + testcase_open++;
1.158 + test_log_printfe ("%s<testcase path=\"%s\">\n", sindent (log_indent), msg->strings[0]);
1.159 + log_indent += 2;
1.160 + break;
1.161 + case G_TEST_LOG_SKIP_CASE:
1.162 + if (FALSE && gtester_verbose) /* enable to debug test case skipping logic */
1.163 + {
1.164 + gchar *sc = g_strconcat (msg->strings[0], ":", NULL);
1.165 + gchar *sleft = g_strdup_printf ("%-68s", sc);
1.166 + g_free (sc);
1.167 + g_print ("%70s SKIPPED\n", sleft);
1.168 + g_free (sleft);
1.169 + }
1.170 + test_log_printfe ("%s<testcase path=\"%s\" skipped=\"1\"/>\n", sindent (log_indent), msg->strings[0]);
1.171 + break;
1.172 + case G_TEST_LOG_STOP_CASE:
1.173 + testcase_close (msg->nums[2], (int) msg->nums[0], (int) msg->nums[1]);
1.174 + break;
1.175 + case G_TEST_LOG_MIN_RESULT:
1.176 + case G_TEST_LOG_MAX_RESULT:
1.177 + test_log_printfe ("%s<performance minimize=\"%d\" maximize=\"%d\" value=\"%.16Lg\">\n",
1.178 + sindent (log_indent), msg->log_type == G_TEST_LOG_MIN_RESULT, msg->log_type == G_TEST_LOG_MAX_RESULT, msg->nums[0]);
1.179 + test_log_printfe ("%s%s\n", sindent (log_indent + 2), msg->strings[0]);
1.180 + test_log_printfe ("%s</performance>\n", sindent (log_indent));
1.181 + break;
1.182 + case G_TEST_LOG_MESSAGE:
1.183 + test_log_printfe ("%s<message>\n%s\n%s</message>\n", sindent (log_indent), msg->strings[0], sindent (log_indent));
1.184 + break;
1.185 + }
1.186 +}
1.187 +
1.188 +static gboolean
1.189 +child_report_cb (GIOChannel *source,
1.190 + GIOCondition condition,
1.191 + gpointer data)
1.192 +{
1.193 + GTestLogBuffer *tlb = data;
1.194 + GIOStatus status = G_IO_STATUS_NORMAL;
1.195 + gboolean first_read_eof = FALSE, first_read = TRUE;
1.196 + gsize length = 0;
1.197 + do
1.198 + {
1.199 + guint8 buffer[READ_BUFFER_SIZE];
1.200 + GError *error = NULL;
1.201 + status = g_io_channel_read_chars (source, (gchar*) buffer, sizeof (buffer), &length, &error);
1.202 + if (first_read && (condition & G_IO_IN))
1.203 + {
1.204 + /* on some unixes (MacOS) we need to detect non-blocking fd EOF
1.205 + * by an IO_IN select/poll followed by read()==0.
1.206 + */
1.207 + first_read_eof = length == 0;
1.208 + }
1.209 + first_read = FALSE;
1.210 + if (length)
1.211 + {
1.212 + GTestLogMsg *msg;
1.213 + g_test_log_buffer_push (tlb, length, buffer);
1.214 + do
1.215 + {
1.216 + msg = g_test_log_buffer_pop (tlb);
1.217 + if (msg)
1.218 + {
1.219 + test_log_msg (msg);
1.220 + g_test_log_msg_free (msg);
1.221 + }
1.222 + }
1.223 + while (msg);
1.224 + }
1.225 + g_clear_error (&error);
1.226 + /* ignore the io channel status, which will report intermediate EOFs for non blocking fds */
1.227 + (void) status;
1.228 + }
1.229 + while (length > 0);
1.230 + /* g_print ("LASTIOSTATE: first_read_eof=%d condition=%d\n", first_read_eof, condition); */
1.231 + if (first_read_eof || (condition & (G_IO_ERR | G_IO_HUP)))
1.232 + {
1.233 + /* if there's no data to read and select() reports an error or hangup,
1.234 + * the fd must have been closed remotely
1.235 + */
1.236 + subtest_io_pending = FALSE;
1.237 + return FALSE;
1.238 + }
1.239 + return TRUE; /* keep polling */
1.240 +}
1.241 +
1.242 +static void
1.243 +child_watch_cb (GPid pid,
1.244 + gint status,
1.245 + gpointer data)
1.246 +{
1.247 + g_spawn_close_pid (pid);
1.248 + if (WIFEXITED (status)) /* normal exit */
1.249 + subtest_exitstatus = WEXITSTATUS (status);
1.250 + else /* signal or core dump, etc */
1.251 + subtest_exitstatus = 0xffffffff;
1.252 + subtest_running = FALSE;
1.253 +}
1.254 +
1.255 +static gchar*
1.256 +queue_gfree (GSList **slistp,
1.257 + gchar *string)
1.258 +{
1.259 + *slistp = g_slist_prepend (*slistp, string);
1.260 + return string;
1.261 +}
1.262 +
1.263 +static void
1.264 +unset_cloexec_fdp (gpointer fdp_data)
1.265 +{
1.266 + int r, *fdp = fdp_data;
1.267 + do
1.268 + r = fcntl (*fdp, F_SETFD, 0 /* FD_CLOEXEC */);
1.269 + while (r < 0 && errno == EINTR);
1.270 +}
1.271 +
1.272 +static gboolean
1.273 +launch_test_binary (const char *binary,
1.274 + guint skip_tests)
1.275 +{
1.276 + GTestLogBuffer *tlb;
1.277 + GSList *slist, *free_list = NULL;
1.278 + GError *error = NULL;
1.279 + int argc = 0;
1.280 + const gchar **argv;
1.281 + GPid pid = 0;
1.282 + gint report_pipe[2] = { -1, -1 };
1.283 + guint child_report_cb_id = 0;
1.284 + gboolean loop_pending;
1.285 + gint i = 0;
1.286 +
1.287 + if (pipe (report_pipe) < 0)
1.288 + {
1.289 + if (subtest_mode_fatal)
1.290 + g_error ("Failed to open pipe for test binary: %s: %s", binary, g_strerror (errno));
1.291 + else
1.292 + g_warning ("Failed to open pipe for test binary: %s: %s", binary, g_strerror (errno));
1.293 + return FALSE;
1.294 + }
1.295 +
1.296 + /* setup argc */
1.297 + for (slist = subtest_args; slist; slist = slist->next)
1.298 + argc++;
1.299 + /* argc++; */
1.300 + if (subtest_quiet)
1.301 + argc++;
1.302 + if (subtest_verbose)
1.303 + argc++;
1.304 + if (!subtest_mode_fatal)
1.305 + argc++;
1.306 + if (subtest_mode_quick)
1.307 + argc++;
1.308 + else
1.309 + argc++;
1.310 + if (subtest_mode_perf)
1.311 + argc++;
1.312 + if (gtester_list_tests)
1.313 + argc++;
1.314 + if (subtest_seedstr)
1.315 + argc++;
1.316 + argc++;
1.317 + if (skip_tests)
1.318 + argc++;
1.319 + for (slist = subtest_paths; slist; slist = slist->next)
1.320 + argc++;
1.321 +
1.322 + /* setup argv */
1.323 + argv = g_malloc ((argc + 2) * sizeof(gchar *));
1.324 + argv[i++] = binary;
1.325 + for (slist = subtest_args; slist; slist = slist->next)
1.326 + argv[i++] = (gchar*) slist->data;
1.327 + /* argv[i++] = "--debug-log"; */
1.328 + if (subtest_quiet)
1.329 + argv[i++] = "--quiet";
1.330 + if (subtest_verbose)
1.331 + argv[i++] = "--verbose";
1.332 + if (!subtest_mode_fatal)
1.333 + argv[i++] = "--keep-going";
1.334 + if (subtest_mode_quick)
1.335 + argv[i++] = "-m=quick";
1.336 + else
1.337 + argv[i++] = "-m=slow";
1.338 + if (subtest_mode_perf)
1.339 + argv[i++] = "-m=perf";
1.340 + if (gtester_list_tests)
1.341 + argv[i++] = "-l";
1.342 + if (subtest_seedstr)
1.343 + argv[i++] = queue_gfree (&free_list, g_strdup_printf ("--seed=%s", subtest_seedstr));
1.344 + argv[i++] = queue_gfree (&free_list, g_strdup_printf ("--GTestLogFD=%u", report_pipe[1]));
1.345 + if (skip_tests)
1.346 + argv[i++] = queue_gfree (&free_list, g_strdup_printf ("--GTestSkipCount=%u", skip_tests));
1.347 + for (slist = subtest_paths; slist; slist = slist->next)
1.348 + argv[i++] = queue_gfree (&free_list, g_strdup_printf ("-p=%s", (gchar*) slist->data));
1.349 + argv[i++] = NULL;
1.350 +
1.351 + g_spawn_async_with_pipes (NULL, /* g_get_current_dir() */
1.352 + (gchar**) argv,
1.353 + NULL, /* envp */
1.354 + G_SPAWN_DO_NOT_REAP_CHILD, /* G_SPAWN_SEARCH_PATH */
1.355 + unset_cloexec_fdp, &report_pipe[1], /* pre-exec callback */
1.356 + &pid,
1.357 + NULL, /* standard_input */
1.358 + NULL, /* standard_output */
1.359 + NULL, /* standard_error */
1.360 + &error);
1.361 + g_slist_foreach (free_list, (void(*)(void*,void*)) g_free, NULL);
1.362 + g_slist_free (free_list);
1.363 + free_list = NULL;
1.364 + close (report_pipe[1]);
1.365 +
1.366 + if (!gtester_quiet)
1.367 + g_print ("(pid=%lu)\n", (unsigned long) pid);
1.368 +
1.369 + if (error)
1.370 + {
1.371 + close (report_pipe[0]);
1.372 + if (subtest_mode_fatal)
1.373 + g_error ("Failed to execute test binary: %s: %s", argv[0], error->message);
1.374 + else
1.375 + g_warning ("Failed to execute test binary: %s: %s", argv[0], error->message);
1.376 + g_clear_error (&error);
1.377 + g_free (argv);
1.378 + return FALSE;
1.379 + }
1.380 + g_free (argv);
1.381 +
1.382 + subtest_running = TRUE;
1.383 + subtest_io_pending = TRUE;
1.384 + tlb = g_test_log_buffer_new();
1.385 + if (report_pipe[0] >= 0)
1.386 + {
1.387 + ioc_report = g_io_channel_unix_new (report_pipe[0]);
1.388 + g_io_channel_set_flags (ioc_report, G_IO_FLAG_NONBLOCK, NULL);
1.389 + g_io_channel_set_encoding (ioc_report, NULL, NULL);
1.390 + g_io_channel_set_buffered (ioc_report, FALSE);
1.391 + child_report_cb_id = g_io_add_watch_full (ioc_report, G_PRIORITY_DEFAULT - 1, G_IO_IN | G_IO_ERR | G_IO_HUP, child_report_cb, tlb, NULL);
1.392 + g_io_channel_unref (ioc_report);
1.393 + }
1.394 + g_child_watch_add_full (G_PRIORITY_DEFAULT + 1, pid, child_watch_cb, NULL, NULL);
1.395 +
1.396 + loop_pending = g_main_context_pending (NULL);
1.397 + while (subtest_running || /* FALSE once child exits */
1.398 + subtest_io_pending || /* FALSE once ioc_report closes */
1.399 + loop_pending) /* TRUE while idler, etc are running */
1.400 + {
1.401 + /* g_print ("LOOPSTATE: subtest_running=%d subtest_io_pending=%d\n", subtest_running, subtest_io_pending); */
1.402 + /* check for unexpected hangs that are not signalled on report_pipe */
1.403 + if (!subtest_running && /* child exited */
1.404 + subtest_io_pending && /* no EOF detected on report_pipe */
1.405 + !loop_pending) /* no IO events pending however */
1.406 + break;
1.407 + g_main_context_iteration (NULL, TRUE);
1.408 + loop_pending = g_main_context_pending (NULL);
1.409 + }
1.410 +
1.411 + g_source_remove (child_report_cb_id);
1.412 + close (report_pipe[0]);
1.413 + g_test_log_buffer_free (tlb);
1.414 +
1.415 + return TRUE;
1.416 +}
1.417 +
1.418 +static void
1.419 +launch_test (const char *binary)
1.420 +{
1.421 + gboolean success = TRUE;
1.422 + GTimer *btimer = g_timer_new();
1.423 + gboolean need_restart;
1.424 + testcase_count = 0;
1.425 + testcase_fail_count = 0;
1.426 + if (!gtester_quiet)
1.427 + g_print ("TEST: %s... ", binary);
1.428 +
1.429 + retry:
1.430 + test_log_printfe ("%s<testbinary path=\"%s\">\n", sindent (log_indent), binary);
1.431 + log_indent += 2;
1.432 + g_timer_start (btimer);
1.433 + subtest_exitstatus = 0;
1.434 + success &= launch_test_binary (binary, testcase_count);
1.435 + success &= subtest_exitstatus == 0;
1.436 + need_restart = testcase_open != 0;
1.437 + if (testcase_open)
1.438 + testcase_close (0, -256, 0);
1.439 + g_timer_stop (btimer);
1.440 + test_log_printfe ("%s<duration>%.6f</duration>\n", sindent (log_indent), g_timer_elapsed (btimer, NULL));
1.441 + log_indent -= 2;
1.442 + test_log_printfe ("%s</testbinary>\n", sindent (log_indent));
1.443 + g_free (subtest_last_seed);
1.444 + subtest_last_seed = NULL;
1.445 + if (need_restart)
1.446 + {
1.447 + /* restart test binary, skipping processed test cases */
1.448 + goto retry;
1.449 + }
1.450 +
1.451 + if (!gtester_quiet)
1.452 + g_print ("%s: %s\n", testcase_fail_count || !success ? "FAIL" : "PASS", binary);
1.453 + g_timer_destroy (btimer);
1.454 + if (subtest_mode_fatal && !success)
1.455 + terminate();
1.456 +}
1.457 +
1.458 +static void
1.459 +usage (gboolean just_version)
1.460 +{
1.461 + if (just_version)
1.462 + {
1.463 + g_print ("gtester version %d.%d.%d\n", GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION, GLIB_MICRO_VERSION);
1.464 + return;
1.465 + }
1.466 + g_print ("Usage: gtester [OPTIONS] testprogram...\n");
1.467 + /* 12345678901234567890123456789012345678901234567890123456789012345678901234567890 */
1.468 + g_print ("Options:\n");
1.469 + g_print (" -h, --help show this help message\n");
1.470 + g_print (" -v, --version print version informations\n");
1.471 + g_print (" --g-fatal-warnings make warnings fatal (abort)\n");
1.472 + g_print (" -k, --keep-going continue running after tests failed\n");
1.473 + g_print (" -l list paths of available test cases\n");
1.474 + g_print (" -m=perf, -m=slow, -m=quick -m=thorough\n");
1.475 + g_print (" run test cases in mode perf, slow/thorough or quick (default)\n");
1.476 + g_print (" -p=TESTPATH only start test cases matching TESTPATH\n");
1.477 + g_print (" --seed=SEEDSTRING start all tests with random number seed SEEDSTRING\n");
1.478 + g_print (" -o=LOGFILE write the test log to LOGFILE\n");
1.479 + g_print (" -q, --quiet suppress per test binary output\n");
1.480 + g_print (" --verbose report success per testcase\n");
1.481 +}
1.482 +
1.483 +static void
1.484 +parse_args (gint *argc_p,
1.485 + gchar ***argv_p)
1.486 +{
1.487 + guint argc = *argc_p;
1.488 + gchar **argv = *argv_p;
1.489 + guint i, e;
1.490 + /* parse known args */
1.491 + for (i = 1; i < argc; i++)
1.492 + {
1.493 + if (strcmp (argv[i], "--g-fatal-warnings") == 0)
1.494 + {
1.495 + GLogLevelFlags fatal_mask = (GLogLevelFlags) g_log_set_always_fatal ((GLogLevelFlags) G_LOG_FATAL_MASK);
1.496 + fatal_mask = (GLogLevelFlags) (fatal_mask | G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL);
1.497 + g_log_set_always_fatal (fatal_mask);
1.498 + argv[i] = NULL;
1.499 + }
1.500 + else if (strcmp (argv[i], "--gtester-selftest") == 0)
1.501 + {
1.502 + gtester_selftest = TRUE;
1.503 + argv[i] = NULL;
1.504 + break; /* stop parsing regular gtester arguments */
1.505 + }
1.506 + else if (strcmp (argv[i], "-h") == 0 || strcmp (argv[i], "--help") == 0)
1.507 + {
1.508 + usage (FALSE);
1.509 + exit (0);
1.510 + argv[i] = NULL;
1.511 + }
1.512 + else if (strcmp (argv[i], "-v") == 0 || strcmp (argv[i], "--version") == 0)
1.513 + {
1.514 + usage (TRUE);
1.515 + exit (0);
1.516 + argv[i] = NULL;
1.517 + }
1.518 + else if (strcmp (argv[i], "--keep-going") == 0 ||
1.519 + strcmp (argv[i], "-k") == 0)
1.520 + {
1.521 + subtest_mode_fatal = FALSE;
1.522 + argv[i] = NULL;
1.523 + }
1.524 + else if (strcmp ("-p", argv[i]) == 0 || strncmp ("-p=", argv[i], 3) == 0)
1.525 + {
1.526 + gchar *equal = argv[i] + 2;
1.527 + if (*equal == '=')
1.528 + subtest_paths = g_slist_prepend (subtest_paths, equal + 1);
1.529 + else if (i + 1 < argc)
1.530 + {
1.531 + argv[i++] = NULL;
1.532 + subtest_paths = g_slist_prepend (subtest_paths, argv[i]);
1.533 + }
1.534 + argv[i] = NULL;
1.535 + }
1.536 + else if (strcmp ("--test-arg", argv[i]) == 0 || strncmp ("--test-arg=", argv[i], 11) == 0)
1.537 + {
1.538 + gchar *equal = argv[i] + 10;
1.539 + if (*equal == '=')
1.540 + subtest_args = g_slist_prepend (subtest_args, equal + 1);
1.541 + else if (i + 1 < argc)
1.542 + {
1.543 + argv[i++] = NULL;
1.544 + subtest_args = g_slist_prepend (subtest_args, argv[i]);
1.545 + }
1.546 + argv[i] = NULL;
1.547 + }
1.548 + else if (strcmp ("-o", argv[i]) == 0 || strncmp ("-o=", argv[i], 3) == 0)
1.549 + {
1.550 + gchar *equal = argv[i] + 2;
1.551 + if (*equal == '=')
1.552 + output_filename = equal + 1;
1.553 + else if (i + 1 < argc)
1.554 + {
1.555 + argv[i++] = NULL;
1.556 + output_filename = argv[i];
1.557 + }
1.558 + argv[i] = NULL;
1.559 + }
1.560 + else if (strcmp ("-m", argv[i]) == 0 || strncmp ("-m=", argv[i], 3) == 0)
1.561 + {
1.562 + gchar *equal = argv[i] + 2;
1.563 + const gchar *mode = "";
1.564 + if (*equal == '=')
1.565 + mode = equal + 1;
1.566 + else if (i + 1 < argc)
1.567 + {
1.568 + argv[i++] = NULL;
1.569 + mode = argv[i];
1.570 + }
1.571 + if (strcmp (mode, "perf") == 0)
1.572 + subtest_mode_perf = TRUE;
1.573 + else if (strcmp (mode, "slow") == 0 || strcmp (mode, "thorough") == 0)
1.574 + subtest_mode_quick = FALSE;
1.575 + else if (strcmp (mode, "quick") == 0)
1.576 + {
1.577 + subtest_mode_quick = TRUE;
1.578 + subtest_mode_perf = FALSE;
1.579 + }
1.580 + else
1.581 + g_error ("unknown test mode: -m %s", mode);
1.582 + argv[i] = NULL;
1.583 + }
1.584 + else if (strcmp ("-q", argv[i]) == 0 || strcmp ("--quiet", argv[i]) == 0)
1.585 + {
1.586 + gtester_quiet = TRUE;
1.587 + gtester_verbose = FALSE;
1.588 + argv[i] = NULL;
1.589 + }
1.590 + else if (strcmp ("--verbose", argv[i]) == 0)
1.591 + {
1.592 + gtester_quiet = FALSE;
1.593 + gtester_verbose = TRUE;
1.594 + argv[i] = NULL;
1.595 + }
1.596 + else if (strcmp ("-l", argv[i]) == 0)
1.597 + {
1.598 + gtester_list_tests = TRUE;
1.599 + argv[i] = NULL;
1.600 + }
1.601 + else if (strcmp ("--seed", argv[i]) == 0 || strncmp ("--seed=", argv[i], 7) == 0)
1.602 + {
1.603 + gchar *equal = argv[i] + 6;
1.604 + if (*equal == '=')
1.605 + subtest_seedstr = equal + 1;
1.606 + else if (i + 1 < argc)
1.607 + {
1.608 + argv[i++] = NULL;
1.609 + subtest_seedstr = argv[i];
1.610 + }
1.611 + argv[i] = NULL;
1.612 + }
1.613 + }
1.614 + /* collapse argv */
1.615 + e = 1;
1.616 + for (i = 1; i < argc; i++)
1.617 + if (argv[i])
1.618 + {
1.619 + argv[e++] = argv[i];
1.620 + if (i >= e)
1.621 + argv[i] = NULL;
1.622 + }
1.623 + *argc_p = e;
1.624 +}
1.625 +
1.626 +int
1.627 +main (int argc,
1.628 + char **argv)
1.629 +{
1.630 + guint ui;
1.631 +
1.632 + /* some unices need SA_RESTART for SIGCHLD to return -EAGAIN for io.
1.633 + * we must fiddle with sigaction() *before* glib is used, otherwise
1.634 + * we could revoke signal hanmdler setups from glib initialization code.
1.635 + */
1.636 + if (TRUE)
1.637 + {
1.638 + struct sigaction sa;
1.639 + struct sigaction osa;
1.640 + sa.sa_handler = SIG_DFL;
1.641 + sigfillset (&sa.sa_mask);
1.642 + sa.sa_flags = SA_RESTART;
1.643 + sigaction (SIGCHLD, &sa, &osa);
1.644 + }
1.645 +
1.646 + g_set_prgname (argv[0]);
1.647 + parse_args (&argc, &argv);
1.648 + if (gtester_selftest)
1.649 + return main_selftest (argc, argv);
1.650 +
1.651 + if (argc <= 1)
1.652 + {
1.653 + usage (FALSE);
1.654 + return 1;
1.655 + }
1.656 +
1.657 + if (output_filename)
1.658 + {
1.659 + log_fd = g_open (output_filename, O_WRONLY | O_CREAT | O_TRUNC, 0666);
1.660 + if (log_fd < 0)
1.661 + g_error ("Failed to open log file '%s': %s", output_filename, g_strerror (errno));
1.662 + }
1.663 +
1.664 + test_log_printfe ("<?xml version=\"1.0\"?>\n");
1.665 + test_log_printfe ("%s<gtester>\n", sindent (log_indent));
1.666 + log_indent += 2;
1.667 + for (ui = 1; ui < argc; ui++)
1.668 + {
1.669 + const char *binary = argv[ui];
1.670 + launch_test (binary);
1.671 + /* we only get here on success or if !subtest_mode_fatal */
1.672 + }
1.673 + log_indent -= 2;
1.674 + test_log_printfe ("%s</gtester>\n", sindent (log_indent));
1.675 +
1.676 + close (log_fd);
1.677 +
1.678 + return 0;
1.679 +}
1.680 +
1.681 +static void
1.682 +fixture_setup (guint *fix,
1.683 + gconstpointer test_data)
1.684 +{
1.685 + g_assert_cmphex (*fix, ==, 0);
1.686 + *fix = 0xdeadbeef;
1.687 +}
1.688 +static void
1.689 +fixture_test (guint *fix,
1.690 + gconstpointer test_data)
1.691 +{
1.692 + g_assert_cmphex (*fix, ==, 0xdeadbeef);
1.693 + g_test_message ("This is a test message API test message.");
1.694 + g_test_bug_base ("http://www.example.com/bugtracker/");
1.695 + g_test_bug ("123");
1.696 + g_test_bug_base ("http://www.example.com/bugtracker?bugnum=%s;cmd=showbug");
1.697 + g_test_bug ("456");
1.698 +}
1.699 +static void
1.700 +fixture_teardown (guint *fix,
1.701 + gconstpointer test_data)
1.702 +{
1.703 + g_assert_cmphex (*fix, ==, 0xdeadbeef);
1.704 +}
1.705 +
1.706 +static int
1.707 +main_selftest (int argc,
1.708 + char **argv)
1.709 +{
1.710 + /* gtester main() for --gtester-selftest invokations */
1.711 + g_test_init (&argc, &argv, NULL);
1.712 + g_test_add ("/gtester/fixture-test", guint, NULL, fixture_setup, fixture_test, fixture_teardown);
1.713 + return g_test_run();
1.714 +}