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.
29 /* the read buffer size in bytes */
30 #define READ_BUFFER_SIZE 4096
32 /* --- prototypes --- */
33 static void parse_args (gint *argc_p,
36 /* --- variables --- */
37 static GIOChannel *ioc_report = NULL;
38 static gboolean subtest_running = FALSE;
39 static gboolean subtest_io_pending = FALSE;
40 static gboolean gtester_quiet = TRUE;
41 static gboolean gtester_verbose = FALSE;
42 static gboolean gtester_list_tests = FALSE;
43 static gboolean subtest_mode_fatal = FALSE;
44 static gboolean subtest_mode_perf = FALSE;
45 static gboolean subtest_mode_quick = TRUE;
46 static const gchar *subtest_seedstr = NULL;
47 static GSList *subtest_paths = NULL;
48 static const gchar *outpu_filename = NULL;
50 /* --- functions --- */
52 child_report_cb (GIOChannel *source,
53 GIOCondition condition,
56 GTestLogBuffer *tlb = data;
57 GIOStatus status = G_IO_STATUS_NORMAL;
61 guint8 buffer[READ_BUFFER_SIZE];
63 status = g_io_channel_read_chars (source, (gchar*) buffer, sizeof (buffer), &length, &error);
67 g_test_log_buffer_push (tlb, length, buffer);
70 msg = g_test_log_buffer_pop (tlb);
74 /* print message, this should be written to an XML log file */
75 g_printerr ("{*GTLOG(%s)", g_test_log_type_name (msg->log_type));
76 for (ui = 0; ui < msg->n_strings; ui++)
77 g_printerr (":{%s}", msg->strings[ui]);
81 for (ui = 0; ui < msg->n_nums; ui++)
82 g_printerr ("%s%.16Lg", ui ? ";" : "", msg->nums[ui]);
85 g_printerr (":GTLOG*}\n");
86 g_test_log_msg_free (msg);
91 g_clear_error (&error);
92 /* ignore the io channel status, which seems to be bogus especially for non blocking fds */
96 if (condition & (G_IO_ERR | G_IO_HUP))
98 /* if there's no data to read and select() reports an error or hangup,
99 * the fd must have been closed remotely
101 subtest_io_pending = FALSE;
104 return TRUE; /* keep polling */
108 child_watch_cb (GPid pid,
112 g_spawn_close_pid (pid);
113 subtest_running = FALSE;
117 queue_gfree (GSList **slistp,
120 *slistp = g_slist_prepend (*slistp, string);
125 unset_cloexec_fdp (gpointer fdp_data)
127 int r, *fdp = fdp_data;
129 r = fcntl (*fdp, F_SETFD, 0 /* FD_CLOEXEC */);
130 while (r < 0 && errno == EINTR);
134 launch_test (const char *binary)
137 GSList *slist, *free_list = NULL;
138 GError *error = NULL;
139 const gchar *argv[20 + g_slist_length (subtest_paths)];
141 gint report_pipe[2] = { -1, -1 };
144 if (pipe (report_pipe) < 0)
146 if (subtest_mode_fatal)
147 g_error ("Failed to open pipe for test binary: %s: %s", binary, g_strerror (errno));
149 g_warning ("Failed to open pipe for test binary: %s: %s", binary, g_strerror (errno));
156 argv[i++] = "--quiet";
158 argv[i++] = "--verbose";
159 // argv[i++] = "--debug-log";
160 argv[i++] = queue_gfree (&free_list, g_strdup_printf ("--GTestLogFD=%u", report_pipe[1]));
161 if (!subtest_mode_fatal)
162 argv[i++] = "--keep-going";
163 if (subtest_mode_quick)
164 argv[i++] = "-m=quick";
166 argv[i++] = "-m=slow";
167 if (subtest_mode_perf)
168 argv[i++] = "-m=perf";
170 argv[i++] = queue_gfree (&free_list, g_strdup_printf ("--seed=%s", subtest_seedstr));
171 for (slist = subtest_paths; slist; slist = slist->next)
172 argv[i++] = queue_gfree (&free_list, g_strdup_printf ("-p=%s", (gchar*) slist->data));
173 if (gtester_list_tests)
177 g_spawn_async_with_pipes (NULL, /* g_get_current_dir() */
180 G_SPAWN_DO_NOT_REAP_CHILD, /* G_SPAWN_SEARCH_PATH */
181 unset_cloexec_fdp, &report_pipe[1], /* pre-exec callback */
183 NULL, /* standard_input */
184 NULL, /* standard_output */
185 NULL, /* standard_error */
187 g_slist_foreach (free_list, (void(*)(void*,void*)) g_free, NULL);
188 g_slist_free (free_list);
190 close (report_pipe[1]);
194 close (report_pipe[0]);
195 if (subtest_mode_fatal)
196 g_error ("Failed to execute test binary: %s: %s", argv[0], error->message);
198 g_warning ("Failed to execute test binary: %s: %s", argv[0], error->message);
199 g_clear_error (&error);
203 subtest_running = TRUE;
204 subtest_io_pending = TRUE;
205 tlb = g_test_log_buffer_new();
206 if (report_pipe[0] >= 0)
208 ioc_report = g_io_channel_unix_new (report_pipe[0]);
209 g_io_channel_set_flags (ioc_report, G_IO_FLAG_NONBLOCK, NULL);
210 g_io_channel_set_encoding (ioc_report, NULL, NULL);
211 g_io_channel_set_buffered (ioc_report, FALSE);
212 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);
213 g_io_channel_unref (ioc_report);
215 g_child_watch_add_full (G_PRIORITY_DEFAULT + 1, pid, child_watch_cb, NULL, NULL);
217 while (subtest_running || /* FALSE once child exits */
218 subtest_io_pending || /* FALSE once ioc_report closes */
219 g_main_context_pending (NULL)) /* TRUE while idler, etc are running */
220 g_main_context_iteration (NULL, TRUE);
222 close (report_pipe[0]);
223 g_test_log_buffer_free (tlb);
227 usage (gboolean just_version)
231 g_print ("gtester version %d.%d.%d\n", GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION, GLIB_MICRO_VERSION);
234 g_print ("Usage: gtester [OPTIONS] testprogram...\n");
235 /* 12345678901234567890123456789012345678901234567890123456789012345678901234567890 */
236 g_print ("Options:\n");
237 g_print (" -h, --help show this help message\n");
238 g_print (" -v, --version print version informations\n");
239 g_print (" --g-fatal-warnings make warnings fatal (abort)\n");
240 g_print (" -k, --keep-going continue running after tests failed\n");
241 g_print (" -l list paths of available test cases\n");
242 g_print (" -m=perf, -m=slow, -m=quick run test cases in mode perf, slow or quick (default)\n");
243 g_print (" -p=TESTPATH only start test cases matching TESTPATH\n");
244 g_print (" --seed=SEEDSTRING start all tests with random number seed SEEDSTRING\n");
245 g_print (" -o=LOGFILE write the test log to LOGFILE\n");
246 g_print (" -q, --quiet suppress unnecessary output\n");
247 g_print (" --verbose produce additional output\n");
251 parse_args (gint *argc_p,
254 guint argc = *argc_p;
255 gchar **argv = *argv_p;
257 /* parse known args */
258 for (i = 1; i < argc; i++)
260 if (strcmp (argv[i], "--g-fatal-warnings") == 0)
262 GLogLevelFlags fatal_mask = (GLogLevelFlags) g_log_set_always_fatal ((GLogLevelFlags) G_LOG_FATAL_MASK);
263 fatal_mask = (GLogLevelFlags) (fatal_mask | G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL);
264 g_log_set_always_fatal (fatal_mask);
267 else if (strcmp (argv[i], "-h") == 0 || strcmp (argv[i], "--help") == 0)
273 else if (strcmp (argv[i], "-v") == 0 || strcmp (argv[i], "--version") == 0)
279 else if (strcmp (argv[i], "--keep-going") == 0 ||
280 strcmp (argv[i], "-k") == 0)
282 subtest_mode_fatal = FALSE;
285 else if (strcmp ("-p", argv[i]) == 0 || strncmp ("-p=", argv[i], 3) == 0)
287 gchar *equal = argv[i] + 2;
289 subtest_paths = g_slist_prepend (subtest_paths, equal + 1);
290 else if (i + 1 < argc)
293 subtest_paths = g_slist_prepend (subtest_paths, argv[i]);
297 else if (strcmp ("-o", argv[i]) == 0 || strncmp ("-o=", argv[i], 3) == 0)
299 gchar *equal = argv[i] + 2;
301 outpu_filename = equal + 1;
302 else if (i + 1 < argc)
305 outpu_filename = argv[i];
309 else if (strcmp ("-m", argv[i]) == 0 || strncmp ("-m=", argv[i], 3) == 0)
311 gchar *equal = argv[i] + 2;
312 const gchar *mode = "";
315 else if (i + 1 < argc)
320 if (strcmp (mode, "perf") == 0)
321 subtest_mode_perf = TRUE;
322 else if (strcmp (mode, "slow") == 0)
323 subtest_mode_quick = FALSE;
324 else if (strcmp (mode, "quick") == 0)
326 subtest_mode_quick = TRUE;
327 subtest_mode_perf = FALSE;
330 g_error ("unknown test mode: -m %s", mode);
333 else if (strcmp ("-q", argv[i]) == 0 || strcmp ("--quiet", argv[i]) == 0)
335 gtester_quiet = TRUE;
336 gtester_verbose = FALSE;
339 else if (strcmp ("--verbose", argv[i]) == 0)
341 gtester_quiet = FALSE;
342 gtester_verbose = TRUE;
345 else if (strcmp ("-l", argv[i]) == 0)
347 gtester_list_tests = TRUE;
350 else if (strcmp ("--seed", argv[i]) == 0 || strncmp ("--seed=", argv[i], 7) == 0)
352 gchar *equal = argv[i] + 6;
354 subtest_seedstr = equal + 1;
355 else if (i + 1 < argc)
358 subtest_seedstr = argv[i];
365 for (i = 1; i < argc; i++)
381 /* some unices need SA_RESTART for SIGCHLD to return -EAGAIN for io.
382 * we must fiddle with sigaction() *before* glib is used, otherwise
383 * we could revoke signal hanmdler setups from glib initialization code.
388 struct sigaction osa;
389 sa.sa_handler = SIG_DFL;
390 sigfillset (&sa.sa_mask);
391 sa.sa_flags = SA_RESTART;
392 sigaction (SIGCHLD, &sa, &osa);
395 g_set_prgname (argv[0]);
396 parse_args (&argc, &argv);
404 for (ui = 1; ui < argc; ui++)
406 const char *binary = argv[ui];
407 launch_test (binary);
410 /* we only get here on success or if !subtest_mode_fatal */