1 /* GLib testing framework examples
2 * Copyright (C) 2007 Tim Janik
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the
16 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 * Boston, MA 02111-1307, USA.
20 #include "gtestframework.h"
21 #include <sys/types.h>
29 #ifdef HAVE_SYS_SELECT_H
30 #include <sys/select.h>
31 #endif /* HAVE_SYS_SELECT_H */
33 /* --- structures --- */
38 void (*fixture_setup) (void*);
39 void (*fixture_test) (void*);
40 void (*fixture_teardown) (void*);
49 /* --- prototypes --- */
50 static void test_run_seed (const gchar *rseed);
51 static void test_trap_clear (void);
53 /* --- variables --- */
54 static int test_stdmsg = 1;
55 static gboolean test_mode_quick = TRUE;
56 static gboolean test_mode_perf = FALSE;
57 static gboolean test_mode_fatal = TRUE;
58 static gboolean g_test_initialized = FALSE;
59 static gboolean g_test_run_once = TRUE;
60 static gboolean test_run_quiet = FALSE;
61 static gboolean test_run_verbose = FALSE;
62 static gboolean test_run_list = FALSE;
63 static gchar *test_run_output = NULL;
64 static gchar *test_run_seedstr = NULL;
65 static GRand *test_run_rand = NULL;
66 static gchar *test_run_name = "";
67 static guint test_run_forks = 0;
68 static GTimer *test_user_timer = NULL;
69 static double test_user_stamp = 0;
70 static GSList *test_paths = NULL;
71 static GTestSuite *test_suite_root = NULL;
72 static GSList *test_run_free_queue = NULL;
73 static int test_trap_last_status = 0;
74 static int test_trap_last_pid = 0;
75 static char *test_trap_last_stdout = NULL;
76 static char *test_trap_last_stderr = NULL;
77 static gboolean test_debug_log = FALSE;
79 /* --- functions --- */
82 G_TEST_LOG_ERROR, // s:msg
83 G_TEST_LOG_START_BINARY, // s:binaryname s:seed
84 G_TEST_LOG_LIST_CASE, // s:testpath
85 G_TEST_LOG_START_CASE, // s:testpath
86 G_TEST_LOG_STOP_CASE, // d:status d:nforks d:elapsed
87 G_TEST_LOG_MIN_RESULT, // s:blurb d:result
88 G_TEST_LOG_MAX_RESULT, // s:blurb d:result
92 test_log_bit (GTestLogBit lbit)
96 case G_TEST_LOG_START_BINARY: return "binary";
97 case G_TEST_LOG_LIST_CASE: return "list";
98 case G_TEST_LOG_START_CASE: return "start";
99 case G_TEST_LOG_STOP_CASE: return "stop";
100 case G_TEST_LOG_MIN_RESULT: return "minperf";
101 case G_TEST_LOG_MAX_RESULT: return "maxperf";
102 default: return "???";
107 g_test_log (GTestLogBit lbit,
108 const gchar *string1,
109 const gchar *string2,
113 gboolean fail = lbit == G_TEST_LOG_STOP_CASE && largs[0] != 0;
114 const char *bit = test_log_bit (lbit);
118 case G_TEST_LOG_STOP_CASE:
120 g_print ("%s\n", fail ? "FAIL" : "OK");
121 if (fail && test_mode_fatal)
124 case G_TEST_LOG_MIN_RESULT:
125 if (test_run_verbose)
126 g_print ("(MINPERF:%s)\n", string1);
128 case G_TEST_LOG_MAX_RESULT:
129 if (test_run_verbose)
130 g_print ("(MAXPERF:%s)\n", string1);
136 g_printerr ("{*LOG(%s)", bit);
137 if (test_debug_log && string1)
138 g_printerr (":{%s}", string1);
139 if (test_debug_log && string2)
140 g_printerr (":{%s}", string2);
146 for (i = 0; i < n_args; i++)
148 if (i && test_debug_log)
151 g_printerr ("%.16Lg", largs[i]);
157 g_printerr (":LOG*}\n");
161 case G_TEST_LOG_START_CASE:
163 g_print ("%s: ", string1);
170 parse_args (gint *argc_p,
173 guint argc = *argc_p;
174 gchar **argv = *argv_p;
176 /* parse known args */
177 for (i = 1; i < argc; i++)
179 if (strcmp (argv[i], "--g-fatal-warnings") == 0)
181 GLogLevelFlags fatal_mask = (GLogLevelFlags) g_log_set_always_fatal ((GLogLevelFlags) G_LOG_FATAL_MASK);
182 fatal_mask = (GLogLevelFlags) (fatal_mask | G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL);
183 g_log_set_always_fatal (fatal_mask);
186 else if (strcmp (argv[i], "--keep-going") == 0 ||
187 strcmp (argv[i], "-k") == 0)
189 test_mode_fatal = FALSE;
192 else if (strcmp (argv[i], "--debug-log") == 0)
194 test_debug_log = TRUE;
197 else if (strcmp ("-p", argv[i]) == 0 || strncmp ("-p=", argv[i], 3) == 0)
199 gchar *equal = argv[i] + 2;
201 test_paths = g_slist_prepend (test_paths, equal + 1);
202 else if (i + 1 < argc)
205 test_paths = g_slist_prepend (test_paths, argv[i]);
209 else if (strcmp ("-o", argv[i]) == 0 || strncmp ("-o=", argv[i], 3) == 0)
211 gchar *equal = argv[i] + 2;
213 test_run_output = equal + 1;
214 else if (i + 1 < argc)
217 test_run_output = argv[i];
221 else if (strcmp ("-m", argv[i]) == 0 || strncmp ("-m=", argv[i], 3) == 0)
223 gchar *equal = argv[i] + 2;
224 const gchar *mode = "";
227 else if (i + 1 < argc)
232 if (strcmp (mode, "perf") == 0)
233 test_mode_perf = TRUE;
234 else if (strcmp (mode, "slow") == 0)
235 test_mode_quick = FALSE;
236 else if (strcmp (mode, "quick") == 0)
238 test_mode_quick = TRUE;
239 test_mode_perf = FALSE;
242 g_error ("unknown test mode: -m %s", mode);
245 else if (strcmp ("-q", argv[i]) == 0 || strcmp ("--quiet", argv[i]) == 0)
247 test_run_quiet = TRUE;
248 test_run_verbose = FALSE;
251 else if (strcmp ("--verbose", argv[i]) == 0)
253 test_run_quiet = FALSE;
254 test_run_verbose = TRUE;
257 else if (strcmp ("-l", argv[i]) == 0)
259 test_run_list = TRUE;
262 else if (strcmp ("--seed", argv[i]) == 0 || strncmp ("--seed=", argv[i], 7) == 0)
264 gchar *equal = argv[i] + 6;
266 test_run_seedstr = equal + 1;
267 else if (i + 1 < argc)
270 test_run_seedstr = argv[i];
277 for (i = 1; i < argc; i++)
288 g_test_init (int *argc,
292 static char seedstr[4 + 4 * 8 + 1];
295 g_return_if_fail (argc != NULL);
296 g_return_if_fail (argv != NULL);
297 g_return_if_fail (g_test_initialized == FALSE);
298 g_test_initialized = TRUE;
300 va_start (args, argv);
301 vararg1 = va_arg (args, gpointer); /* reserved for future extensions */
303 g_return_if_fail (vararg1 == NULL);
305 /* setup random seed string */
306 g_snprintf (seedstr, sizeof (seedstr), "R02S%08x%08x%08x%08x", g_random_int(), g_random_int(), g_random_int(), g_random_int());
307 test_run_seedstr = seedstr;
309 /* parse args, sets up mode, changes seed, etc. */
310 parse_args (argc, argv);
311 if (!g_get_prgname())
312 g_set_prgname ((*argv)[0]);
314 /* verify GRand reliability, needed for reliable seeds */
317 GRand *rg = g_rand_new_with_seed (0xc8c49fb6);
318 guint32 t1 = g_rand_int (rg), t2 = g_rand_int (rg), t3 = g_rand_int (rg), t4 = g_rand_int (rg);
319 // g_print ("GRand-current: 0x%x 0x%x 0x%x 0x%x\n", t1, t2, t3, t4);
320 if (t1 != 0xfab39f9b || t2 != 0xb948fb0e || t3 != 0x3d31be26 || t4 != 0x43a19d66)
321 g_warning ("random numbers are not GRand-2.2 compatible, seeds may be broken (check $G_RANDOM_VERSION)");
325 /* check rand seed */
326 test_run_seed (test_run_seedstr);
328 /* report program start */
329 g_test_log (G_TEST_LOG_START_BINARY, g_get_prgname(), test_run_seedstr, 0, NULL);
333 test_run_seed (const gchar *rseed)
335 guint seed_failed = 0;
337 g_rand_free (test_run_rand);
338 test_run_rand = NULL;
339 while (strchr (" \t\v\r\n\f", *rseed))
341 if (strncmp (rseed, "R02S", 4) == 0) // seed for random generator 02 (GRand-2.2)
343 const char *s = rseed + 4;
344 if (strlen (s) >= 32) // require 4 * 8 chars
346 guint32 seedarray[4];
347 gchar *p, hexbuf[9] = { 0, };
348 memcpy (hexbuf, s + 0, 8);
349 seedarray[0] = g_ascii_strtoull (hexbuf, &p, 16);
350 seed_failed += p != NULL && *p != 0;
351 memcpy (hexbuf, s + 8, 8);
352 seedarray[1] = g_ascii_strtoull (hexbuf, &p, 16);
353 seed_failed += p != NULL && *p != 0;
354 memcpy (hexbuf, s + 16, 8);
355 seedarray[2] = g_ascii_strtoull (hexbuf, &p, 16);
356 seed_failed += p != NULL && *p != 0;
357 memcpy (hexbuf, s + 24, 8);
358 seedarray[3] = g_ascii_strtoull (hexbuf, &p, 16);
359 seed_failed += p != NULL && *p != 0;
362 test_run_rand = g_rand_new_with_seed_array (seedarray, 4);
367 g_error ("Unknown or invalid random seed: %s", rseed);
371 g_test_rand_int (void)
373 return g_rand_int (test_run_rand);
377 g_test_rand_int_range (gint32 begin,
380 return g_rand_int_range (test_run_rand, begin, end);
384 g_test_rand_double (void)
386 return g_rand_double (test_run_rand);
390 g_test_rand_double_range (double range_start,
393 return g_rand_double_range (test_run_rand, range_start, range_end);
397 g_test_timer_start (void)
399 if (!test_user_timer)
400 test_user_timer = g_timer_new();
402 g_timer_start (test_user_timer);
406 g_test_timer_elapsed (void)
408 test_user_stamp = test_user_timer ? g_timer_elapsed (test_user_timer, NULL) : 0;
409 return test_user_stamp;
413 g_test_timer_last (void)
415 return test_user_stamp;
419 g_test_minimized_result (double minimized_quantity,
423 long double largs = minimized_quantity;
426 va_start (args, format);
427 buffer = g_strdup_vprintf (format, args);
429 g_test_log (G_TEST_LOG_MIN_RESULT, buffer, NULL, 1, &largs);
434 g_test_maximized_result (double maximized_quantity,
438 long double largs = maximized_quantity;
441 va_start (args, format);
442 buffer = g_strdup_vprintf (format, args);
444 g_test_log (G_TEST_LOG_MAX_RESULT, buffer, NULL, 1, &largs);
449 g_test_get_root (void)
451 if (!test_suite_root)
453 test_suite_root = g_test_create_suite ("root");
454 g_free (test_suite_root->name);
455 test_suite_root->name = g_strdup ("");
457 return test_suite_root;
463 return g_test_run_suite (g_test_get_root());
467 g_test_create_case (const char *test_name,
469 void (*data_setup) (void),
470 void (*data_test) (void),
471 void (*data_teardown) (void))
473 g_return_val_if_fail (test_name != NULL, NULL);
474 g_return_val_if_fail (strchr (test_name, '/') == NULL, NULL);
475 g_return_val_if_fail (test_name[0] != 0, NULL);
476 g_return_val_if_fail (data_test != NULL, NULL);
477 GTestCase *tc = g_slice_new0 (GTestCase);
478 tc->name = g_strdup (test_name);
479 tc->fixture_size = data_size;
480 tc->fixture_setup = (void*) data_setup;
481 tc->fixture_test = (void*) data_test;
482 tc->fixture_teardown = (void*) data_teardown;
487 g_test_add_vtable (const char *testpath,
489 void (*data_setup) (void),
490 void (*fixture_test_func) (void),
491 void (*data_teardown) (void))
497 g_return_if_fail (testpath != NULL);
498 g_return_if_fail (testpath[0] == '/');
499 g_return_if_fail (fixture_test_func != NULL);
501 suite = g_test_get_root();
502 segments = g_strsplit (testpath, "/", -1);
503 for (ui = 0; segments[ui] != NULL; ui++)
505 const char *seg = segments[ui];
506 gboolean islast = segments[ui + 1] == NULL;
507 if (islast && !seg[0])
508 g_error ("invalid test case path: %s", testpath);
510 continue; // initial or duplicate slash
513 GTestSuite *csuite = g_test_create_suite (seg);
514 g_test_suite_add_suite (suite, csuite);
519 GTestCase *tc = g_test_create_case (seg, data_size, data_setup, fixture_test_func, data_teardown);
520 g_test_suite_add (suite, tc);
523 g_strfreev (segments);
527 g_test_add_func (const char *testpath,
528 void (*test_func) (void))
530 g_return_if_fail (testpath != NULL);
531 g_return_if_fail (testpath[0] == '/');
532 g_return_if_fail (test_func != NULL);
533 g_test_add_vtable (testpath, 0, NULL, test_func, NULL);
537 g_test_create_suite (const char *suite_name)
539 g_return_val_if_fail (suite_name != NULL, NULL);
540 g_return_val_if_fail (strchr (suite_name, '/') == NULL, NULL);
541 g_return_val_if_fail (suite_name[0] != 0, NULL);
542 GTestSuite *ts = g_slice_new0 (GTestSuite);
543 ts->name = g_strdup (suite_name);
548 g_test_suite_add (GTestSuite *suite,
549 GTestCase *test_case)
551 g_return_if_fail (suite != NULL);
552 g_return_if_fail (test_case != NULL);
553 suite->cases = g_slist_prepend (suite->cases, test_case);
557 g_test_suite_add_suite (GTestSuite *suite,
558 GTestSuite *nestedsuite)
560 g_return_if_fail (suite != NULL);
561 g_return_if_fail (nestedsuite != NULL);
562 suite->suites = g_slist_prepend (suite->suites, nestedsuite);
566 g_test_queue_free (gpointer gfree_pointer)
569 test_run_free_queue = g_slist_prepend (test_run_free_queue, gfree_pointer);
573 test_case_run (GTestCase *tc)
576 old_name = test_run_name;
577 test_run_name = g_strconcat (old_name, "/", tc->name, NULL);
580 g_print ("%s\n", test_run_name);
581 g_test_log (G_TEST_LOG_LIST_CASE, test_run_name, NULL, 0, NULL);
585 GTimer *test_run_timer = g_timer_new();
586 long double largs[3];
587 g_test_log (G_TEST_LOG_START_CASE, test_run_name, NULL, 0, NULL);
589 g_timer_start (test_run_timer);
590 void *fixture = g_malloc0 (tc->fixture_size);
591 test_run_seed (test_run_seedstr);
592 if (tc->fixture_setup)
593 tc->fixture_setup (fixture);
594 tc->fixture_test (fixture);
596 while (test_run_free_queue)
598 gpointer freeme = test_run_free_queue->data;
599 test_run_free_queue = g_slist_delete_link (test_run_free_queue, test_run_free_queue);
602 if (tc->fixture_teardown)
603 tc->fixture_teardown (fixture);
605 g_timer_stop (test_run_timer);
607 largs[1] = test_run_forks;
608 largs[2] = g_timer_elapsed (test_run_timer, NULL);
609 g_test_log (G_TEST_LOG_STOP_CASE, NULL, NULL, G_N_ELEMENTS (largs), largs);
611 g_free (test_run_name);
612 test_run_name = old_name;
613 /* FIXME: need reporting here */
618 g_test_run_suite_internal (GTestSuite *suite,
621 guint n_bad = 0, n_good = 0, bad_suite = 0, l;
622 gchar *rest, *old_name = test_run_name;
623 GSList *slist, *reversed;
624 g_return_val_if_fail (suite != NULL, -1);
625 while (path[0] == '/')
628 rest = strchr (path, '/');
629 l = rest ? MIN (l, rest - path) : l;
630 test_run_name = suite->name[0] == 0 ? g_strdup (test_run_name) : g_strconcat (old_name, "/", suite->name, NULL);
631 reversed = g_slist_reverse (g_slist_copy (suite->cases));
632 for (slist = reversed; slist; slist = slist->next)
634 GTestCase *tc = slist->data;
635 guint n = l ? strlen (tc->name) : 0;
636 if (l == n && strncmp (path, tc->name, n) == 0)
639 n_bad += test_case_run (tc) != 0;
642 g_slist_free (reversed);
643 reversed = g_slist_reverse (g_slist_copy (suite->suites));
644 for (slist = reversed; slist; slist = slist->next)
646 GTestSuite *ts = slist->data;
647 guint n = l ? strlen (ts->name) : 0;
648 if (l == n && strncmp (path, ts->name, n) == 0)
649 bad_suite += g_test_run_suite_internal (ts, rest ? rest : "") != 0;
651 g_slist_free (reversed);
652 g_free (test_run_name);
653 test_run_name = old_name;
654 return n_bad || bad_suite;
658 g_test_run_suite (GTestSuite *suite)
661 g_return_val_if_fail (g_test_initialized == TRUE, -1);
662 g_return_val_if_fail (g_test_run_once == TRUE, -1);
663 g_test_run_once = FALSE;
665 test_paths = g_slist_prepend (test_paths, "");
668 const char *rest, *path = test_paths->data;
670 test_paths = g_slist_delete_link (test_paths, test_paths);
671 while (path[0] == '/')
673 rest = strchr (path, '/');
675 l = rest ? MIN (l, rest - path) : l;
676 n = l ? strlen (suite->name) : 0;
677 if (l == n && strncmp (path, suite->name, n) == 0)
678 n_bad += 0 != g_test_run_suite_internal (suite, rest ? rest : "");
684 g_assertion_message (const char *domain,
691 g_snprintf (lstr, 32, "%d", line);
692 char *s = g_strconcat (domain ? domain : "", domain && domain[0] ? ":" : "",
693 file, ":", lstr, ":",
694 func, func[0] ? ":" : "",
696 g_printerr ("**\n** %s\n", s);
702 g_assertion_message_expr (const char *domain,
708 char *s = g_strconcat ("assertion failed: (", expr, ")", NULL);
709 g_assertion_message (domain, file, line, func, s);
714 g_assertion_message_cmpnum (const char *domain,
727 case 'i': s = g_strdup_printf ("assertion failed (%s): (%.0Lf %s %.0Lf)", expr, arg1, cmp, arg2); break;
728 case 'x': s = g_strdup_printf ("assertion failed (%s): (0x%08Lx %s 0x%08Lx)", expr, (guint64) arg1, cmp, (guint64) arg2); break;
729 case 'f': s = g_strdup_printf ("assertion failed (%s): (%.9Lg %s %.9Lg)", expr, arg1, cmp, arg2); break;
730 /* ideally use: floats=%.7g double=%.17g */
732 g_assertion_message (domain, file, line, func, s);
737 g_assertion_message_cmpstr (const char *domain,
746 char *a1, *a2, *s, *t1 = NULL, *t2 = NULL;
747 a1 = arg1 ? g_strconcat ("\"", t1 = g_strescape (arg1, NULL), "\"", NULL) : g_strdup ("NULL");
748 a2 = arg2 ? g_strconcat ("\"", t2 = g_strescape (arg2, NULL), "\"", NULL) : g_strdup ("NULL");
751 s = g_strdup_printf ("assertion failed (%s): (%s %s %s)", expr, a1, cmp, a2);
754 g_assertion_message (domain, file, line, func, s);
759 g_strcmp0 (const char *str1,
763 return -(str1 != str2);
766 return strcmp (str1, str2);
769 static int /* 0 on success */
775 if (patience >= 3) /* try graceful reap */
777 if (waitpid (pid, status, WNOHANG) > 0)
780 if (patience >= 2) /* try SIGHUP */
783 if (waitpid (pid, status, WNOHANG) > 0)
785 g_usleep (20 * 1000); /* give it some scheduling/shutdown time */
786 if (waitpid (pid, status, WNOHANG) > 0)
788 g_usleep (50 * 1000); /* give it some scheduling/shutdown time */
789 if (waitpid (pid, status, WNOHANG) > 0)
791 g_usleep (100 * 1000); /* give it some scheduling/shutdown time */
792 if (waitpid (pid, status, WNOHANG) > 0)
795 if (patience >= 1) /* try SIGTERM */
798 if (waitpid (pid, status, WNOHANG) > 0)
800 g_usleep (200 * 1000); /* give it some scheduling/shutdown time */
801 if (waitpid (pid, status, WNOHANG) > 0)
803 g_usleep (400 * 1000); /* give it some scheduling/shutdown time */
804 if (waitpid (pid, status, WNOHANG) > 0)
810 wr = waitpid (pid, status, 0);
811 while (wr < 0 && errno == EINTR);
816 g_string_must_read (GString *gstring,
819 #define STRING_BUFFER_SIZE 4096
820 char buf[STRING_BUFFER_SIZE];
823 bytes = read (fd, buf, sizeof (buf));
825 return 0; /* EOF, calling this function assumes data is available */
828 g_string_append_len (gstring, buf, bytes);
831 else if (bytes < 0 && errno == EINTR)
835 g_warning ("failed to read() from child process (%d): %s", test_trap_last_pid, g_strerror (errno));
836 return 1; /* ignore error after warning */
841 g_string_write_out (GString *gstring,
845 if (*stringpos < gstring->len)
849 r = write (outfd, gstring->str + *stringpos, gstring->len - *stringpos);
850 while (r < 0 && errno == EINTR);
851 *stringpos += MAX (r, 0);
861 ret = dup2 (fd1, fd2);
862 while (ret < 0 && errno == EINTR);
867 test_trap_clear (void)
869 test_trap_last_status = 0;
870 test_trap_last_pid = 0;
871 g_free (test_trap_last_stdout);
872 test_trap_last_stdout = NULL;
873 g_free (test_trap_last_stderr);
874 test_trap_last_stderr = NULL;
878 test_time_stamp (void)
882 g_get_current_time (&tv);
884 stamp = stamp * 1000000 + tv.tv_usec;
889 g_test_trap_fork (guint64 usec_timeout,
890 GTestTrapFlags test_trap_flags)
892 int stdout_pipe[2] = { -1, -1 };
893 int stderr_pipe[2] = { -1, -1 };
894 int stdtst_pipe[2] = { -1, -1 };
896 if (pipe (stdout_pipe) < 0 || pipe (stderr_pipe) < 0 || pipe (stdtst_pipe) < 0)
897 g_error ("failed to create pipes to fork test program: %s", g_strerror (errno));
898 signal (SIGCHLD, SIG_DFL);
899 test_trap_last_pid = fork ();
900 if (test_trap_last_pid < 0)
901 g_error ("failed to fork test program: %s", g_strerror (errno));
902 if (test_trap_last_pid == 0) /* child */
905 close (stdout_pipe[0]);
906 close (stderr_pipe[0]);
907 close (stdtst_pipe[0]);
908 if (!(test_trap_flags & G_TEST_TRAP_INHERIT_STDIN))
909 fd0 = open ("/dev/null", O_RDONLY);
910 if (sane_dup2 (stdout_pipe[1], 1) < 0 || sane_dup2 (stderr_pipe[1], 2) < 0 || (fd0 >= 0 && sane_dup2 (fd0, 0) < 0))
911 g_error ("failed to dup2() in forked test program: %s", g_strerror (errno));
914 if (stdout_pipe[1] >= 3)
915 close (stdout_pipe[1]);
916 if (stderr_pipe[1] >= 3)
917 close (stderr_pipe[1]);
918 test_stdmsg = stdtst_pipe[1];
923 GString *sout = g_string_new (NULL);
924 GString *serr = g_string_new (NULL);
925 GString *stst = g_string_new (NULL);
927 int soutpos = 0, serrpos = 0, ststpos = 0, wr, need_wait = TRUE;
929 close (stdout_pipe[1]);
930 close (stderr_pipe[1]);
931 close (stdtst_pipe[1]);
932 sstamp = test_time_stamp();
933 /* read data until we get EOF on all pipes */
934 while (stdout_pipe[0] >= 0 || stderr_pipe[0] >= 0 || stdtst_pipe[0] > 0)
939 if (stdout_pipe[0] >= 0)
940 FD_SET (stdout_pipe[0], &fds);
941 if (stderr_pipe[0] >= 0)
942 FD_SET (stderr_pipe[0], &fds);
943 if (stdtst_pipe[0] >= 0)
944 FD_SET (stdtst_pipe[0], &fds);
946 tv.tv_usec = MIN (usec_timeout ? usec_timeout : 1000000, 100 * 1000); // sleep at most 0.5 seconds to catch clock skews, etc.
947 int ret = select (MAX (MAX (stdout_pipe[0], stderr_pipe[0]), stdtst_pipe[0]) + 1, &fds, NULL, NULL, &tv);
948 if (ret < 0 && errno != EINTR)
950 g_warning ("Unexpected error in select() while reading from child process (%d): %s", test_trap_last_pid, g_strerror (errno));
953 if (stdout_pipe[0] >= 0 && FD_ISSET (stdout_pipe[0], &fds) &&
954 g_string_must_read (sout, stdout_pipe[0]) == 0)
956 close (stdout_pipe[0]);
959 if (stderr_pipe[0] >= 0 && FD_ISSET (stderr_pipe[0], &fds) &&
960 g_string_must_read (serr, stderr_pipe[0]) == 0)
962 close (stderr_pipe[0]);
965 if (stdtst_pipe[0] >= 0 && FD_ISSET (stdtst_pipe[0], &fds) &&
966 g_string_must_read (stst, stdtst_pipe[0]) == 0)
968 close (stdtst_pipe[0]);
971 if (!(test_trap_flags & G_TEST_TRAP_SILENCE_STDOUT))
972 g_string_write_out (sout, 1, &soutpos);
973 if (!(test_trap_flags & G_TEST_TRAP_SILENCE_STDERR))
974 g_string_write_out (serr, 2, &serrpos);
975 if (TRUE) // FIXME: needs capturing into log file
976 g_string_write_out (stst, 1, &ststpos);
979 guint64 nstamp = test_time_stamp();
981 sstamp = MIN (sstamp, nstamp); // guard against backwards clock skews
982 if (usec_timeout < nstamp - sstamp)
984 /* timeout reached, need to abort the child now */
985 kill_child (test_trap_last_pid, &status, 3);
986 test_trap_last_status = 1024; /* timeout */
987 if (0 && WIFSIGNALED (status))
988 g_printerr ("%s: child timed out and received: %s\n", G_STRFUNC, g_strsignal (WTERMSIG (status)));
994 close (stdout_pipe[0]);
995 close (stderr_pipe[0]);
996 close (stdtst_pipe[0]);
1001 wr = waitpid (test_trap_last_pid, &status, 0);
1002 while (wr < 0 && errno == EINTR);
1003 if (WIFEXITED (status)) /* normal exit */
1004 test_trap_last_status = WEXITSTATUS (status); /* 0..255 */
1005 else if (WIFSIGNALED (status))
1006 test_trap_last_status = (WTERMSIG (status) << 12); /* signalled */
1007 else /* WCOREDUMP (status) */
1008 test_trap_last_status = 512; /* coredump */
1010 test_trap_last_stdout = g_string_free (sout, FALSE);
1011 test_trap_last_stderr = g_string_free (serr, FALSE);
1012 g_string_free (stst, TRUE);
1018 g_test_trap_has_passed (void)
1020 return test_trap_last_status == 0; /* exit_status == 0 && !signal && !coredump */
1024 g_test_trap_reached_timeout (void)
1026 return 0 != (test_trap_last_status & 1024); /* timeout flag */
1030 g_test_trap_assertions (const char *domain,
1036 const char *stdout_pattern,
1037 const char *stderr_pattern)
1039 if (test_trap_last_pid == 0)
1040 g_error ("child process failed to exit after g_test_trap_fork() and before g_test_trap_assert*()");
1041 if (must_pass && !g_test_trap_has_passed())
1043 char *msg = g_strdup_printf ("child process (%d) of test trap failed unexpectedly", test_trap_last_pid);
1044 g_assertion_message (domain, file, line, func, msg);
1047 if (must_fail && g_test_trap_has_passed())
1049 char *msg = g_strdup_printf ("child process (%d) did not fail as expected", test_trap_last_pid);
1050 g_assertion_message (domain, file, line, func, msg);
1053 if (stdout_pattern && !g_pattern_match_simple (stdout_pattern, test_trap_last_stdout))
1055 char *msg = g_strdup_printf ("stdout of child process (%d) failed to match: %s", test_trap_last_pid, stdout_pattern);
1056 g_assertion_message (domain, file, line, func, msg);
1059 if (stderr_pattern && !g_pattern_match_simple (stderr_pattern, test_trap_last_stderr))
1061 char *msg = g_strdup_printf ("stderr of child process (%d) failed to match: %s", test_trap_last_pid, stderr_pattern);
1062 g_assertion_message (domain, file, line, func, msg);