1 /* GLib testing framework runner
2 * Copyright (C) 2007 Sven Herzberg
3 * Copyright (C) 2007 Tim Janik
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
28 /* the read buffer size in bytes */
29 #define READ_BUFFER_SIZE 4096
31 /* --- prototypes --- */
32 static void parse_args (gint *argc_p,
35 /* --- variables --- */
36 static GIOChannel *ioc_report = NULL;
37 static gboolean subtest_running = FALSE;
38 static gboolean subtest_io_pending = FALSE;
39 static gboolean gtester_quiet = TRUE;
40 static gboolean gtester_verbose = FALSE;
41 static gboolean gtester_list_tests = FALSE;
42 static gboolean subtest_mode_fatal = FALSE;
43 static gboolean subtest_mode_perf = FALSE;
44 static gboolean subtest_mode_quick = TRUE;
45 static const gchar *subtest_seedstr = NULL;
46 static GSList *subtest_paths = NULL;
47 static const gchar *outpu_filename = NULL;
49 /* --- functions --- */
51 child_report_cb (GIOChannel *source,
52 GIOCondition condition,
55 GTestLogBuffer *tlb = data;
56 GIOStatus status = G_IO_STATUS_NORMAL;
60 guint8 buffer[READ_BUFFER_SIZE];
62 status = g_io_channel_read_chars (source, (gchar*) buffer, sizeof (buffer), &length, &error);
66 g_test_log_buffer_push (tlb, length, buffer);
69 msg = g_test_log_buffer_pop (tlb);
73 /* print message, this should be written to an XML log file */
74 g_printerr ("{*GTLOG(%s)", g_test_log_type_name (msg->log_type));
75 for (ui = 0; ui < msg->n_strings; ui++)
76 g_printerr (":{%s}", msg->strings[ui]);
80 for (ui = 0; ui < msg->n_nums; ui++)
81 g_printerr ("%s%.16Lg", ui ? ";" : "", msg->nums[ui]);
84 g_printerr (":GTLOG*}\n");
85 g_test_log_msg_free (msg);
90 g_clear_error (&error);
91 /* ignore the io channel status, which seems to be bogus especially for non blocking fds */
95 if (condition & (G_IO_ERR | G_IO_HUP))
97 /* if there's no data to read and select() reports an error or hangup,
98 * the fd must have been closed remotely
100 subtest_io_pending = FALSE;
103 return TRUE; /* keep polling */
107 child_watch_cb (GPid pid,
111 g_spawn_close_pid (pid);
112 subtest_running = FALSE;
116 queue_gfree (GSList **slistp,
119 *slistp = g_slist_prepend (*slistp, string);
124 unset_cloexec_fdp (gpointer fdp_data)
126 int r, *fdp = fdp_data;
128 r = fcntl (*fdp, F_SETFD, 0 /* FD_CLOEXEC */);
129 while (r < 0 && errno == EINTR);
133 launch_test (const char *binary)
136 GSList *slist, *free_list = NULL;
137 GError *error = NULL;
138 const gchar *argv[20 + g_slist_length (subtest_paths)];
140 gint report_pipe[2] = { -1, -1 };
143 if (pipe (report_pipe) < 0)
145 if (subtest_mode_fatal)
146 g_error ("Failed to open pipe for test binary: %s: %s", binary, g_strerror (errno));
148 g_warning ("Failed to open pipe for test binary: %s: %s", binary, g_strerror (errno));
155 argv[i++] = "--quiet";
157 argv[i++] = "--verbose";
158 // argv[i++] = "--debug-log";
159 argv[i++] = queue_gfree (&free_list, g_strdup_printf ("--GTestLogFD=%u", report_pipe[1]));
160 if (!subtest_mode_fatal)
161 argv[i++] = "--keep-going";
162 if (subtest_mode_quick)
163 argv[i++] = "-m=quick";
165 argv[i++] = "-m=slow";
166 if (subtest_mode_perf)
167 argv[i++] = "-m=perf";
169 argv[i++] = queue_gfree (&free_list, g_strdup_printf ("--seed=%s", subtest_seedstr));
170 for (slist = subtest_paths; slist; slist = slist->next)
171 argv[i++] = queue_gfree (&free_list, g_strdup_printf ("-p=%s", (gchar*) slist->data));
172 if (gtester_list_tests)
176 g_spawn_async_with_pipes (NULL, /* g_get_current_dir() */
179 G_SPAWN_DO_NOT_REAP_CHILD, /* G_SPAWN_SEARCH_PATH */
180 unset_cloexec_fdp, &report_pipe[1], /* pre-exec callback */
182 NULL, /* standard_input */
183 NULL, /* standard_output */
184 NULL, /* standard_error */
186 g_slist_foreach (free_list, (void(*)(void*,void*)) g_free, NULL);
187 g_slist_free (free_list);
189 close (report_pipe[1]);
193 close (report_pipe[0]);
194 if (subtest_mode_fatal)
195 g_error ("Failed to execute test binary: %s: %s", argv[0], error->message);
197 g_warning ("Failed to execute test binary: %s: %s", argv[0], error->message);
198 g_clear_error (&error);
202 subtest_running = TRUE;
203 subtest_io_pending = TRUE;
204 tlb = g_test_log_buffer_new();
205 if (report_pipe[0] >= 0)
207 ioc_report = g_io_channel_unix_new (report_pipe[0]);
208 g_io_channel_set_flags (ioc_report, G_IO_FLAG_NONBLOCK, NULL);
209 g_io_channel_set_encoding (ioc_report, NULL, NULL);
210 g_io_channel_set_buffered (ioc_report, FALSE);
211 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);
212 g_io_channel_unref (ioc_report);
214 g_child_watch_add_full (G_PRIORITY_DEFAULT + 1, pid, child_watch_cb, NULL, NULL);
216 while (subtest_running || /* FALSE once child exits */
217 subtest_io_pending || /* FALSE once ioc_report closes */
218 g_main_context_pending (NULL)) /* TRUE while idler, etc are running */
219 g_main_context_iteration (NULL, TRUE);
221 close (report_pipe[0]);
222 g_test_log_buffer_free (tlb);
226 usage (gboolean just_version)
230 g_print ("gtester version %d.%d.%d\n", GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION, GLIB_MICRO_VERSION);
233 g_print ("Usage: gtester [OPTIONS] testprogram...\n");
234 /* 12345678901234567890123456789012345678901234567890123456789012345678901234567890 */
235 g_print ("Options:\n");
236 g_print (" -h, --help show this help message\n");
237 g_print (" -v, --version print version informations\n");
238 g_print (" --g-fatal-warnings make warnings fatal (abort)\n");
239 g_print (" -k, --keep-going continue running after tests failed\n");
240 g_print (" -l list paths of available test cases\n");
241 g_print (" -m=perf, -m=slow, -m=quick run test cases in mode perf, slow or quick (default)\n");
242 g_print (" -p=TESTPATH only start test cases matching TESTPATH\n");
243 g_print (" --seed=SEEDSTRING start all tests with random number seed SEEDSTRING\n");
244 g_print (" -o=LOGFILE write the test log to LOGFILE\n");
245 g_print (" -q, --quiet suppress unnecessary output\n");
246 g_print (" --verbose produce additional output\n");
250 parse_args (gint *argc_p,
253 guint argc = *argc_p;
254 gchar **argv = *argv_p;
256 /* parse known args */
257 for (i = 1; i < argc; i++)
259 if (strcmp (argv[i], "--g-fatal-warnings") == 0)
261 GLogLevelFlags fatal_mask = (GLogLevelFlags) g_log_set_always_fatal ((GLogLevelFlags) G_LOG_FATAL_MASK);
262 fatal_mask = (GLogLevelFlags) (fatal_mask | G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL);
263 g_log_set_always_fatal (fatal_mask);
266 else if (strcmp (argv[i], "-h") == 0 || strcmp (argv[i], "--help") == 0)
272 else if (strcmp (argv[i], "-v") == 0 || strcmp (argv[i], "--version") == 0)
278 else if (strcmp (argv[i], "--keep-going") == 0 ||
279 strcmp (argv[i], "-k") == 0)
281 subtest_mode_fatal = FALSE;
284 else if (strcmp ("-p", argv[i]) == 0 || strncmp ("-p=", argv[i], 3) == 0)
286 gchar *equal = argv[i] + 2;
288 subtest_paths = g_slist_prepend (subtest_paths, equal + 1);
289 else if (i + 1 < argc)
292 subtest_paths = g_slist_prepend (subtest_paths, argv[i]);
296 else if (strcmp ("-o", argv[i]) == 0 || strncmp ("-o=", argv[i], 3) == 0)
298 gchar *equal = argv[i] + 2;
300 outpu_filename = equal + 1;
301 else if (i + 1 < argc)
304 outpu_filename = argv[i];
308 else if (strcmp ("-m", argv[i]) == 0 || strncmp ("-m=", argv[i], 3) == 0)
310 gchar *equal = argv[i] + 2;
311 const gchar *mode = "";
314 else if (i + 1 < argc)
319 if (strcmp (mode, "perf") == 0)
320 subtest_mode_perf = TRUE;
321 else if (strcmp (mode, "slow") == 0)
322 subtest_mode_quick = FALSE;
323 else if (strcmp (mode, "quick") == 0)
325 subtest_mode_quick = TRUE;
326 subtest_mode_perf = FALSE;
329 g_error ("unknown test mode: -m %s", mode);
332 else if (strcmp ("-q", argv[i]) == 0 || strcmp ("--quiet", argv[i]) == 0)
334 gtester_quiet = TRUE;
335 gtester_verbose = FALSE;
338 else if (strcmp ("--verbose", argv[i]) == 0)
340 gtester_quiet = FALSE;
341 gtester_verbose = TRUE;
344 else if (strcmp ("-l", argv[i]) == 0)
346 gtester_list_tests = TRUE;
349 else if (strcmp ("--seed", argv[i]) == 0 || strncmp ("--seed=", argv[i], 7) == 0)
351 gchar *equal = argv[i] + 6;
353 subtest_seedstr = equal + 1;
354 else if (i + 1 < argc)
357 subtest_seedstr = argv[i];
364 for (i = 1; i < argc; i++)
380 /* some unices need SA_RESTART for SIGCHLD to return -EAGAIN for io.
381 * we must fiddle with sigaction() *before* glib is used, otherwise
382 * we could revoke signal hanmdler setups from glib initialization code.
387 struct sigaction osa;
388 sa.sa_handler = SIG_DFL;
389 sigfillset (&sa.sa_mask);
390 sa.sa_flags = SA_RESTART;
391 sigaction (SIGCHLD, &sa, &osa);
394 g_set_prgname (argv[0]);
395 parse_args (&argc, &argv);
403 for (ui = 1; ui < argc; ui++)
405 const char *binary = argv[ui];
406 launch_test (binary);
409 /* we only get here on success or if !subtest_mode_fatal */