LCOV - code coverage report
Current view: top level - glib - gtester.c (source / functions) Coverage Total Hit
Test: unnamed Lines: 62.4 % 442 276
Test Date: 2025-03-04 05:20:05 Functions: 88.9 % 18 16
Branches: - 0 0

             Branch data     Line data    Source code
       1                 :             : /* GLib testing framework runner
       2                 :             :  * Copyright (C) 2007 Sven Herzberg
       3                 :             :  * Copyright (C) 2007 Tim Janik
       4                 :             :  *
       5                 :             :  * SPDX-License-Identifier: LGPL-2.1-or-later
       6                 :             :  *
       7                 :             :  * This library is free software; you can redistribute it and/or
       8                 :             :  * modify it under the terms of the GNU Lesser General Public
       9                 :             :  * License as published by the Free Software Foundation; either
      10                 :             :  * version 2.1 of the License, or (at your option) any later version.
      11                 :             :  *
      12                 :             :  * This library is distributed in the hope that it will be useful,
      13                 :             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14                 :             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      15                 :             :  * Lesser General Public License for more details.
      16                 :             :  *
      17                 :             :  * You should have received a copy of the GNU Lesser General Public
      18                 :             :  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
      19                 :             :  */
      20                 :             : #include "config.h"
      21                 :             : 
      22                 :             : #include <glib.h>
      23                 :             : #include <glib-unix.h>
      24                 :             : #include <gstdio.h>
      25                 :             : #include <string.h>
      26                 :             : #include <stdlib.h>
      27                 :             : #include <unistd.h>
      28                 :             : #include <fcntl.h>
      29                 :             : #include <sys/wait.h>
      30                 :             : #include <errno.h>
      31                 :             : #include <signal.h>
      32                 :             : 
      33                 :             : /* the read buffer size in bytes */
      34                 :             : #define READ_BUFFER_SIZE 4096
      35                 :             : 
      36                 :             : /* --- prototypes --- */
      37                 :             : static int      main_selftest   (int    argc,
      38                 :             :                                  char **argv);
      39                 :             : static void     parse_args      (gint           *argc_p,
      40                 :             :                                  gchar        ***argv_p);
      41                 :             : 
      42                 :             : /* --- variables --- */
      43                 :             : static GIOChannel  *ioc_report = NULL;
      44                 :             : static gboolean     gtester_quiet = FALSE;
      45                 :             : static gboolean     gtester_verbose = FALSE;
      46                 :             : static gboolean     gtester_list_tests = FALSE;
      47                 :             : static gboolean     gtester_selftest = FALSE;
      48                 :             : static gboolean     gtester_ignore_deprecation = FALSE;
      49                 :             : static gboolean     subtest_running = FALSE;
      50                 :             : static gint         subtest_exitstatus = 0;
      51                 :             : static gboolean     subtest_io_pending = FALSE;
      52                 :             : static gboolean     subtest_quiet = TRUE;
      53                 :             : static gboolean     subtest_verbose = FALSE;
      54                 :             : static gboolean     subtest_mode_fatal = TRUE;
      55                 :             : static gboolean     subtest_mode_perf = FALSE;
      56                 :             : static gboolean     subtest_mode_quick = TRUE;
      57                 :             : static gboolean     subtest_mode_undefined = TRUE;
      58                 :             : static const gchar *subtest_seedstr = NULL;
      59                 :             : static gchar       *subtest_last_seed = NULL;
      60                 :             : static GSList      *subtest_paths = NULL;
      61                 :             : static GSList      *skipped_paths = NULL;
      62                 :             : static GSList      *subtest_args = NULL;
      63                 :             : static gboolean     testcase_open = FALSE;
      64                 :             : static guint        testcase_count = 0;
      65                 :             : static guint        testcase_fail_count = 0;
      66                 :             : static const gchar *output_filename = NULL;
      67                 :             : static guint        log_indent = 0;
      68                 :             : static gint         log_fd = -1;
      69                 :             : 
      70                 :             : /* --- functions --- */
      71                 :             : static const char*
      72                 :          19 : sindent (guint n)
      73                 :             : {
      74                 :             :   static const char spaces[] = "                                                                                                    ";
      75                 :          19 :   gsize l = sizeof (spaces) - 1;
      76                 :          19 :   n = MIN (n, l);
      77                 :          19 :   return spaces + l - n;
      78                 :             : }
      79                 :             : 
      80                 :             : static void G_GNUC_PRINTF (1, 2)
      81                 :          17 : test_log_printfe (const char *format,
      82                 :             :                   ...)
      83                 :             : {
      84                 :             :   char *result;
      85                 :             :   int r;
      86                 :             :   va_list args;
      87                 :          17 :   va_start (args, format);
      88                 :          17 :   result = g_markup_vprintf_escaped (format, args);
      89                 :          17 :   va_end (args);
      90                 :             :   do
      91                 :          17 :     r = write (log_fd, result, strlen (result));
      92                 :          17 :   while (r < 0 && errno == EINTR);
      93                 :          17 :   g_free (result);
      94                 :          17 : }
      95                 :             : 
      96                 :             : static void
      97                 :           0 : terminate (void)
      98                 :             : {
      99                 :           0 :   kill (getpid(), SIGTERM);
     100                 :           0 :   g_abort();
     101                 :             : }
     102                 :             : 
     103                 :             : static void
     104                 :           1 : testcase_close (long double duration,
     105                 :             :                 gint        exit_status,
     106                 :             :                 guint       n_forks)
     107                 :             : {
     108                 :             :   gboolean success;
     109                 :             : 
     110                 :           1 :   g_return_if_fail (testcase_open > 0);
     111                 :           1 :   test_log_printfe ("%s<duration>%.6Lf</duration>\n", sindent (log_indent), duration);
     112                 :           1 :   success = exit_status == G_TEST_RUN_SUCCESS || exit_status == G_TEST_RUN_SKIPPED;
     113                 :           1 :   test_log_printfe ("%s<status exit-status=\"%d\" n-forks=\"%d\" result=\"%s\"/>\n",
     114                 :             :                     sindent (log_indent), exit_status, n_forks,
     115                 :             :                     success ? "success" : "failed");
     116                 :           1 :   log_indent -= 2;
     117                 :           1 :   test_log_printfe ("%s</testcase>\n", sindent (log_indent));
     118                 :           1 :   testcase_open--;
     119                 :           1 :   if (gtester_verbose)
     120                 :             :     {
     121                 :           0 :       switch (exit_status)
     122                 :             :         {
     123                 :           0 :         case G_TEST_RUN_SUCCESS:
     124                 :           0 :           g_print ("OK\n");
     125                 :           0 :           break;
     126                 :           0 :         case G_TEST_RUN_SKIPPED:
     127                 :           0 :           g_print ("SKIP\n");
     128                 :           0 :           break;
     129                 :           0 :         default:
     130                 :           0 :           g_print ("FAIL\n");
     131                 :           0 :           break;
     132                 :             :         }
     133                 :             :     }
     134                 :           1 :   if (!success && subtest_last_seed)
     135                 :           0 :     g_print ("GTester: last random seed: %s\n", subtest_last_seed);
     136                 :           1 :   if (!success)
     137                 :           0 :     testcase_fail_count += 1;
     138                 :           1 :   if (subtest_mode_fatal && !success)
     139                 :           0 :     terminate();
     140                 :             : }
     141                 :             : 
     142                 :             : static void
     143                 :          11 : test_log_msg (GTestLogMsg *msg)
     144                 :             : {
     145                 :          11 :   switch (msg->log_type)
     146                 :             :     {
     147                 :             :       guint i;
     148                 :             :       gchar **strv;
     149                 :           4 :     case G_TEST_LOG_NONE:
     150                 :             :     case G_TEST_LOG_START_SUITE:
     151                 :             :     case G_TEST_LOG_STOP_SUITE:
     152                 :           4 :       break;
     153                 :           0 :     case G_TEST_LOG_ERROR:
     154                 :           0 :       strv = g_strsplit (msg->strings[0], "\n", -1);
     155                 :           0 :       for (i = 0; strv[i]; i++)
     156                 :           0 :         test_log_printfe ("%s<error>%s</error>\n", sindent (log_indent), strv[i]);
     157                 :           0 :       g_strfreev (strv);
     158                 :           0 :       break;
     159                 :           1 :     case G_TEST_LOG_START_BINARY:
     160                 :           1 :       test_log_printfe ("%s<binary file=\"%s\"/>\n", sindent (log_indent), msg->strings[0]);
     161                 :           1 :       subtest_last_seed = g_strdup (msg->strings[1]);
     162                 :           1 :       test_log_printfe ("%s<random-seed>%s</random-seed>\n", sindent (log_indent), subtest_last_seed);
     163                 :           1 :       break;
     164                 :           0 :     case G_TEST_LOG_LIST_CASE:
     165                 :           0 :       g_print ("%s\n", msg->strings[0]);
     166                 :           0 :       break;
     167                 :           1 :     case G_TEST_LOG_START_CASE:
     168                 :           1 :       testcase_count++;
     169                 :           1 :       if (gtester_verbose)
     170                 :             :         {
     171                 :           0 :           gchar *sc = g_strconcat (msg->strings[0], ":", NULL);
     172                 :           0 :           gchar *sleft = g_strdup_printf ("%-68s", sc);
     173                 :           0 :           g_free (sc);
     174                 :           0 :           g_print ("%70s ", sleft);
     175                 :           0 :           g_free (sleft);
     176                 :             :         }
     177                 :           1 :       g_return_if_fail (testcase_open == 0);
     178                 :           1 :       testcase_open++;
     179                 :           1 :       test_log_printfe ("%s<testcase path=\"%s\">\n", sindent (log_indent), msg->strings[0]);
     180                 :           1 :       log_indent += 2;
     181                 :           1 :       break;
     182                 :           0 :     case G_TEST_LOG_SKIP_CASE:
     183                 :             :       if (FALSE && gtester_verbose) /* enable to debug test case skipping logic */
     184                 :             :         {
     185                 :             :           gchar *sc = g_strconcat (msg->strings[0], ":", NULL);
     186                 :             :           gchar *sleft = g_strdup_printf ("%-68s", sc);
     187                 :             :           g_free (sc);
     188                 :             :           g_print ("%70s SKIPPED\n", sleft);
     189                 :             :           g_free (sleft);
     190                 :             :         }
     191                 :           0 :       test_log_printfe ("%s<testcase path=\"%s\" skipped=\"1\"/>\n", sindent (log_indent), msg->strings[0]);
     192                 :           0 :       break;
     193                 :           1 :     case G_TEST_LOG_STOP_CASE:
     194                 :           1 :       testcase_close (msg->nums[2], (int) msg->nums[0], (int) msg->nums[1]);
     195                 :           1 :       break;
     196                 :           0 :     case G_TEST_LOG_MIN_RESULT:
     197                 :             :     case G_TEST_LOG_MAX_RESULT:
     198                 :           0 :       test_log_printfe ("%s<performance minimize=\"%d\" maximize=\"%d\" value=\"%.16Lg\">\n",
     199                 :           0 :                         sindent (log_indent), msg->log_type == G_TEST_LOG_MIN_RESULT, msg->log_type == G_TEST_LOG_MAX_RESULT, msg->nums[0]);
     200                 :           0 :       test_log_printfe ("%s%s\n", sindent (log_indent + 2), msg->strings[0]);
     201                 :           0 :       test_log_printfe ("%s</performance>\n", sindent (log_indent));
     202                 :           0 :       break;
     203                 :           4 :     case G_TEST_LOG_MESSAGE:
     204                 :           4 :       test_log_printfe ("%s<message>\n%s\n%s</message>\n", sindent (log_indent), msg->strings[0], sindent (log_indent));
     205                 :           4 :       break;
     206                 :             :     }
     207                 :             : }
     208                 :             : 
     209                 :             : static gboolean
     210                 :           2 : child_report_cb (GIOChannel  *source,
     211                 :             :                  GIOCondition condition,
     212                 :             :                  gpointer     data)
     213                 :             : {
     214                 :           2 :   GTestLogBuffer *tlb = data;
     215                 :           2 :   GIOStatus status = G_IO_STATUS_NORMAL;
     216                 :           2 :   gboolean first_read_eof = FALSE, first_read = TRUE;
     217                 :           2 :   gsize length = 0;
     218                 :             :   do
     219                 :             :     {
     220                 :             :       guint8 buffer[READ_BUFFER_SIZE];
     221                 :           3 :       GError *error = NULL;
     222                 :           3 :       status = g_io_channel_read_chars (source, (gchar*) buffer, sizeof (buffer), &length, &error);
     223                 :           3 :       if (first_read && (condition & G_IO_IN))
     224                 :             :         {
     225                 :             :           /* on some unixes (MacOS) we need to detect non-blocking fd EOF
     226                 :             :            * by an IO_IN select/poll followed by read()==0.
     227                 :             :            */
     228                 :           1 :           first_read_eof = length == 0;
     229                 :             :         }
     230                 :           3 :       first_read = FALSE;
     231                 :           3 :       if (length)
     232                 :             :         {
     233                 :             :           GTestLogMsg *msg;
     234                 :           1 :           g_test_log_buffer_push (tlb, length, buffer);
     235                 :             :           do
     236                 :             :             {
     237                 :          12 :               msg = g_test_log_buffer_pop (tlb);
     238                 :          12 :               if (msg)
     239                 :             :                 {
     240                 :          11 :                   test_log_msg (msg);
     241                 :          11 :                   g_test_log_msg_free (msg);
     242                 :             :                 }
     243                 :             :             }
     244                 :          12 :           while (msg);
     245                 :             :         }
     246                 :           3 :       g_clear_error (&error);
     247                 :             :       /* ignore the io channel status, which will report intermediate EOFs for non blocking fds */
     248                 :             :       (void) status;
     249                 :             :     }
     250                 :           3 :   while (length > 0);
     251                 :             :   /* g_print ("LASTIOSTATE: first_read_eof=%d condition=%d\n", first_read_eof, condition); */
     252                 :           2 :   if (first_read_eof || (condition & (G_IO_ERR | G_IO_HUP)))
     253                 :             :     {
     254                 :             :       /* if there's no data to read and select() reports an error or hangup,
     255                 :             :        * the fd must have been closed remotely
     256                 :             :        */
     257                 :           1 :       subtest_io_pending = FALSE;
     258                 :           1 :       return FALSE;
     259                 :             :     }
     260                 :           1 :   return TRUE; /* keep polling */
     261                 :             : }
     262                 :             : 
     263                 :             : static void
     264                 :           1 : child_watch_cb (GPid     pid,
     265                 :             :                 gint     status,
     266                 :             :                 gpointer data)
     267                 :             : {
     268                 :           1 :   g_spawn_close_pid (pid);
     269                 :           1 :   if (WIFEXITED (status)) /* normal exit */
     270                 :           1 :     subtest_exitstatus = WEXITSTATUS (status);
     271                 :             :   else /* signal or core dump, etc */
     272                 :           0 :     subtest_exitstatus = 0xffffffff;
     273                 :           1 :   subtest_running = FALSE;
     274                 :           1 : }
     275                 :             : 
     276                 :             : static gchar*
     277                 :           1 : queue_gfree (GSList **slistp,
     278                 :             :              gchar   *string)
     279                 :             : {
     280                 :           1 :   *slistp = g_slist_prepend (*slistp, string);
     281                 :           1 :   return string;
     282                 :             : }
     283                 :             : 
     284                 :             : static void
     285                 :           1 : unset_cloexec_fdp (gpointer fdp_data)
     286                 :             : {
     287                 :           1 :   int r, *fdp = fdp_data;
     288                 :             :   do
     289                 :           1 :     r = fcntl (*fdp, F_SETFD, 0 /* FD_CLOEXEC */);
     290                 :           1 :   while (r < 0 && errno == EINTR);
     291                 :           1 : }
     292                 :             : 
     293                 :             : static gboolean
     294                 :           1 : launch_test_binary (const char *binary,
     295                 :             :                     guint       skip_tests)
     296                 :             : {
     297                 :             :   GTestLogBuffer *tlb;
     298                 :           1 :   GSList *slist, *free_list = NULL;
     299                 :           1 :   GError *error = NULL;
     300                 :           1 :   int argc = 0;
     301                 :             :   const gchar **argv;
     302                 :           1 :   GPid pid = 0;
     303                 :           1 :   gint report_pipe[2] = { -1, -1 };
     304                 :           1 :   guint child_report_cb_id = 0;
     305                 :             :   gboolean loop_pending;
     306                 :           1 :   gint i = 0;
     307                 :             : 
     308                 :           1 :   if (!g_unix_open_pipe (report_pipe, O_CLOEXEC, &error))
     309                 :             :     {
     310                 :           0 :       if (subtest_mode_fatal)
     311                 :           0 :         g_error ("Failed to open pipe for test binary: %s: %s", binary, error->message);
     312                 :             :       else
     313                 :           0 :         g_warning ("Failed to open pipe for test binary: %s: %s", binary, error->message);
     314                 :           0 :       g_clear_error (&error);
     315                 :           0 :       return FALSE;
     316                 :             :     }
     317                 :             : 
     318                 :             :   /* setup argc */
     319                 :           2 :   for (slist = subtest_args; slist; slist = slist->next)
     320                 :           1 :     argc++;
     321                 :             :   /* argc++; */
     322                 :           1 :   if (subtest_quiet)
     323                 :           1 :     argc++;
     324                 :           1 :   if (subtest_verbose)
     325                 :           0 :     argc++;
     326                 :           1 :   if (!subtest_mode_fatal)
     327                 :           1 :     argc++;
     328                 :             :   /* Either -m=quick or -m=slow is always appended. */
     329                 :           1 :   argc++;
     330                 :           1 :   if (subtest_mode_perf)
     331                 :           0 :     argc++;
     332                 :           1 :   if (!subtest_mode_undefined)
     333                 :           0 :     argc++;
     334                 :           1 :   if (gtester_list_tests)
     335                 :           0 :     argc++;
     336                 :           1 :   if (subtest_seedstr)
     337                 :           0 :     argc++;
     338                 :           1 :   argc++;
     339                 :           1 :   if (skip_tests)
     340                 :           0 :     argc++;
     341                 :           1 :   for (slist = subtest_paths; slist; slist = slist->next)
     342                 :           0 :     argc++;
     343                 :           1 :   for (slist = skipped_paths; slist; slist = slist->next)
     344                 :           0 :     argc++;
     345                 :             : 
     346                 :             :   /* setup argv */
     347                 :           1 :   argv = g_malloc ((argc + 2) * sizeof(gchar *));
     348                 :           1 :   argv[i++] = binary;
     349                 :           2 :   for (slist = subtest_args; slist; slist = slist->next)
     350                 :           1 :     argv[i++] = (gchar*) slist->data;
     351                 :             :   /* argv[i++] = "--debug-log"; */
     352                 :           1 :   if (subtest_quiet)
     353                 :           1 :     argv[i++] = "--quiet";
     354                 :           1 :   if (subtest_verbose)
     355                 :           0 :     argv[i++] = "--verbose";
     356                 :           1 :   if (!subtest_mode_fatal)
     357                 :           1 :     argv[i++] = "--keep-going";
     358                 :           1 :   if (subtest_mode_quick)
     359                 :           1 :     argv[i++] = "-m=quick";
     360                 :             :   else
     361                 :           0 :     argv[i++] = "-m=slow";
     362                 :           1 :   if (subtest_mode_perf)
     363                 :           0 :     argv[i++] = "-m=perf";
     364                 :           1 :   if (!subtest_mode_undefined)
     365                 :           0 :     argv[i++] = "-m=no-undefined";
     366                 :           1 :   if (gtester_list_tests)
     367                 :           0 :     argv[i++] = "-l";
     368                 :           1 :   if (subtest_seedstr)
     369                 :           0 :     argv[i++] = queue_gfree (&free_list, g_strdup_printf ("--seed=%s", subtest_seedstr));
     370                 :           1 :   argv[i++] = queue_gfree (&free_list, g_strdup_printf ("--GTestLogFD=%u", report_pipe[1]));
     371                 :           1 :   if (skip_tests)
     372                 :           0 :     argv[i++] = queue_gfree (&free_list, g_strdup_printf ("--GTestSkipCount=%u", skip_tests));
     373                 :           1 :   for (slist = subtest_paths; slist; slist = slist->next)
     374                 :           0 :     argv[i++] = queue_gfree (&free_list, g_strdup_printf ("-p=%s", (gchar*) slist->data));
     375                 :           1 :   for (slist = skipped_paths; slist; slist = slist->next)
     376                 :           0 :     argv[i++] = queue_gfree (&free_list, g_strdup_printf ("-s=%s", (gchar*) slist->data));
     377                 :           1 :   argv[i++] = NULL;
     378                 :             : 
     379                 :           1 :   g_spawn_async_with_pipes (NULL, /* g_get_current_dir() */
     380                 :             :                             (gchar**) argv,
     381                 :             :                             NULL, /* envp */
     382                 :             :                             G_SPAWN_DO_NOT_REAP_CHILD, /* G_SPAWN_SEARCH_PATH */
     383                 :             :                             unset_cloexec_fdp, &report_pipe[1], /* pre-exec callback */
     384                 :             :                             &pid,
     385                 :             :                             NULL,       /* standard_input */
     386                 :             :                             NULL,       /* standard_output */
     387                 :             :                             NULL,       /* standard_error */
     388                 :             :                             &error);
     389                 :           1 :   g_slist_foreach (free_list, (void(*)(void*,void*)) g_free, NULL);
     390                 :           1 :   g_slist_free (free_list);
     391                 :           1 :   free_list = NULL;
     392                 :           1 :   close (report_pipe[1]);
     393                 :             : 
     394                 :           1 :   if (!gtester_quiet)
     395                 :           0 :     g_print ("(pid=%lu)\n", (unsigned long) pid);
     396                 :             : 
     397                 :           1 :   if (error)
     398                 :             :     {
     399                 :           0 :       close (report_pipe[0]);
     400                 :           0 :       if (subtest_mode_fatal)
     401                 :           0 :         g_error ("Failed to execute test binary: %s: %s", argv[0], error->message);
     402                 :             :       else
     403                 :           0 :         g_warning ("Failed to execute test binary: %s: %s", argv[0], error->message);
     404                 :           0 :       g_clear_error (&error);
     405                 :           0 :       g_free (argv);
     406                 :           0 :       return FALSE;
     407                 :             :     }
     408                 :           1 :   g_free (argv);
     409                 :             : 
     410                 :           1 :   subtest_running = TRUE;
     411                 :           1 :   subtest_io_pending = TRUE;
     412                 :           1 :   tlb = g_test_log_buffer_new();
     413                 :           1 :   if (report_pipe[0] >= 0)
     414                 :             :     {
     415                 :           1 :       ioc_report = g_io_channel_unix_new (report_pipe[0]);
     416                 :           1 :       g_io_channel_set_flags (ioc_report, G_IO_FLAG_NONBLOCK, NULL);
     417                 :           1 :       g_io_channel_set_encoding (ioc_report, NULL, NULL);
     418                 :           1 :       g_io_channel_set_buffered (ioc_report, FALSE);
     419                 :           1 :       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);
     420                 :           1 :       g_io_channel_unref (ioc_report);
     421                 :             :     }
     422                 :           1 :   g_child_watch_add_full (G_PRIORITY_DEFAULT + 1, pid, child_watch_cb, NULL, NULL);
     423                 :             : 
     424                 :           1 :   loop_pending = g_main_context_pending (NULL);
     425                 :           2 :   while (subtest_running ||     /* FALSE once child exits */
     426                 :           5 :          subtest_io_pending ||  /* FALSE once ioc_report closes */
     427                 :             :          loop_pending)          /* TRUE while idler, etc are running */
     428                 :             :     {
     429                 :             :       /* g_print ("LOOPSTATE: subtest_running=%d subtest_io_pending=%d\n", subtest_running, subtest_io_pending); */
     430                 :             :       /* check for unexpected hangs that are not signalled on report_pipe */
     431                 :           3 :       if (!subtest_running &&   /* child exited */
     432                 :           0 :           subtest_io_pending && /* no EOF detected on report_pipe */
     433                 :             :           !loop_pending)        /* no IO events pending however */
     434                 :           0 :         break;
     435                 :           3 :       g_main_context_iteration (NULL, TRUE);
     436                 :           3 :       loop_pending = g_main_context_pending (NULL);
     437                 :             :     }
     438                 :             : 
     439                 :           1 :   if (subtest_io_pending)
     440                 :           0 :     g_source_remove (child_report_cb_id);
     441                 :             : 
     442                 :           1 :   close (report_pipe[0]);
     443                 :           1 :   g_test_log_buffer_free (tlb);
     444                 :             : 
     445                 :           1 :   return TRUE;
     446                 :             : }
     447                 :             : 
     448                 :             : static void
     449                 :           1 : launch_test (const char *binary)
     450                 :             : {
     451                 :           1 :   gboolean success = TRUE;
     452                 :           1 :   GTimer *btimer = g_timer_new();
     453                 :             :   gboolean need_restart;
     454                 :             : 
     455                 :           1 :   testcase_count = 0;
     456                 :           1 :   if (!gtester_quiet)
     457                 :           0 :     g_print ("TEST: %s... ", binary);
     458                 :             : 
     459                 :           1 :  retry:
     460                 :           1 :   test_log_printfe ("%s<testbinary path=\"%s\">\n", sindent (log_indent), binary);
     461                 :           1 :   log_indent += 2;
     462                 :           1 :   g_timer_start (btimer);
     463                 :           1 :   subtest_exitstatus = 0;
     464                 :           1 :   success &= launch_test_binary (binary, testcase_count);
     465                 :           1 :   success &= subtest_exitstatus == 0;
     466                 :           1 :   need_restart = testcase_open != 0;
     467                 :           1 :   if (testcase_open)
     468                 :           0 :     testcase_close (0, -256, 0);
     469                 :           1 :   g_timer_stop (btimer);
     470                 :           1 :   test_log_printfe ("%s<duration>%.6f</duration>\n", sindent (log_indent), g_timer_elapsed (btimer, NULL));
     471                 :           1 :   log_indent -= 2;
     472                 :           1 :   test_log_printfe ("%s</testbinary>\n", sindent (log_indent));
     473                 :           1 :   g_free (subtest_last_seed);
     474                 :           1 :   subtest_last_seed = NULL;
     475                 :           1 :   if (need_restart)
     476                 :             :     {
     477                 :             :       /* restart test binary, skipping processed test cases */
     478                 :           0 :       goto retry;
     479                 :             :     }
     480                 :             : 
     481                 :             :   /* count the inability to run a test as a failure */
     482                 :           1 :   if (!success && testcase_count == 0)
     483                 :           0 :     testcase_fail_count++;
     484                 :             : 
     485                 :           1 :   if (!gtester_quiet)
     486                 :           0 :     g_print ("%s: %s\n", !success ? "FAIL" : "PASS", binary);
     487                 :           1 :   g_timer_destroy (btimer);
     488                 :           1 :   if (subtest_mode_fatal && !success)
     489                 :           0 :     terminate();
     490                 :           1 : }
     491                 :             : 
     492                 :             : static void
     493                 :           0 : usage (gboolean just_version)
     494                 :             : {
     495                 :           0 :   if (just_version)
     496                 :             :     {
     497                 :           0 :       g_print ("gtester version %d.%d.%d\n", GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION, GLIB_MICRO_VERSION);
     498                 :           0 :       return;
     499                 :             :     }
     500                 :           0 :   g_print ("Usage:\n");
     501                 :           0 :   g_print ("gtester [OPTIONS] testprogram...\n\n");
     502                 :             :   /*        12345678901234567890123456789012345678901234567890123456789012345678901234567890 */
     503                 :           0 :   g_print ("Help Options:\n");
     504                 :           0 :   g_print ("  -h, --help                    Show this help message\n\n");
     505                 :           0 :   g_print ("Utility Options:\n");
     506                 :           0 :   g_print ("  -v, --version                 Print version information\n");
     507                 :           0 :   g_print ("  --g-fatal-warnings            Make warnings fatal (abort)\n");
     508                 :           0 :   g_print ("  -k, --keep-going              Continue running after tests failed\n");
     509                 :           0 :   g_print ("  -l                            List paths of available test cases\n");
     510                 :           0 :   g_print ("  -m {perf|slow|thorough|quick} Run test cases according to mode\n");
     511                 :           0 :   g_print ("  -m {undefined|no-undefined}   Run test cases according to mode\n");
     512                 :           0 :   g_print ("  -p=TESTPATH                   Only start test cases matching TESTPATH\n");
     513                 :           0 :   g_print ("  -s=TESTPATH                   Skip test cases matching TESTPATH\n");
     514                 :           0 :   g_print ("  --seed=SEEDSTRING             Start tests with random seed SEEDSTRING\n");
     515                 :           0 :   g_print ("  -o=LOGFILE                    Write the test log to LOGFILE\n");
     516                 :           0 :   g_print ("  -q, --quiet                   Suppress per test binary output\n");
     517                 :           0 :   g_print ("  --verbose                     Report success per testcase\n");
     518                 :             : }
     519                 :             : 
     520                 :             : static void
     521                 :           2 : parse_args (gint    *argc_p,
     522                 :             :             gchar ***argv_p)
     523                 :             : {
     524                 :           2 :   guint argc = *argc_p;
     525                 :           2 :   gchar **argv = *argv_p;
     526                 :             :   guint i, e;
     527                 :             :   /* parse known args */
     528                 :           8 :   for (i = 1; i < argc; i++)
     529                 :             :     {
     530                 :           7 :       if (strcmp (argv[i], "--g-fatal-warnings") == 0)
     531                 :             :         {
     532                 :           0 :           GLogLevelFlags fatal_mask = (GLogLevelFlags) g_log_set_always_fatal ((GLogLevelFlags) G_LOG_FATAL_MASK);
     533                 :           0 :           fatal_mask = (GLogLevelFlags) (fatal_mask | G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL);
     534                 :           0 :           g_log_set_always_fatal (fatal_mask);
     535                 :           0 :           argv[i] = NULL;
     536                 :             :         }
     537                 :           7 :       else if (strcmp (argv[i], "--gtester-selftest") == 0)
     538                 :             :         {
     539                 :           1 :           gtester_selftest = TRUE;
     540                 :           1 :           argv[i] = NULL;
     541                 :           1 :           break;        /* stop parsing regular gtester arguments */
     542                 :             :         }
     543                 :           6 :       else if (strcmp (argv[i], "-h") == 0 || strcmp (argv[i], "--help") == 0)
     544                 :             :         {
     545                 :           0 :           usage (FALSE);
     546                 :           0 :           exit (0);
     547                 :             :           argv[i] = NULL;
     548                 :             :         }
     549                 :           6 :       else if (strcmp (argv[i], "-v") == 0 || strcmp (argv[i], "--version") == 0)
     550                 :             :         {
     551                 :           0 :           usage (TRUE);
     552                 :           0 :           exit (0);
     553                 :             :           argv[i] = NULL;
     554                 :             :         }
     555                 :           6 :       else if (strcmp (argv[i], "--keep-going") == 0 ||
     556                 :           6 :                strcmp (argv[i], "-k") == 0)
     557                 :             :         {
     558                 :           1 :           subtest_mode_fatal = FALSE;
     559                 :           1 :           argv[i] = NULL;
     560                 :             :         }
     561                 :           5 :       else if (strcmp ("-p", argv[i]) == 0 || strncmp ("-p=", argv[i], 3) == 0)
     562                 :           0 :         {
     563                 :           0 :           gchar *equal = argv[i] + 2;
     564                 :           0 :           if (*equal == '=')
     565                 :           0 :             subtest_paths = g_slist_prepend (subtest_paths, equal + 1);
     566                 :           0 :           else if (i + 1 < argc)
     567                 :             :             {
     568                 :           0 :               argv[i++] = NULL;
     569                 :           0 :               subtest_paths = g_slist_prepend (subtest_paths, argv[i]);
     570                 :             :             }
     571                 :           0 :           argv[i] = NULL;
     572                 :             :         }
     573                 :           5 :       else if (strcmp ("-s", argv[i]) == 0 || strncmp ("-s=", argv[i], 3) == 0)
     574                 :           0 :         {
     575                 :           0 :           gchar *equal = argv[i] + 2;
     576                 :           0 :           if (*equal == '=')
     577                 :           0 :             skipped_paths = g_slist_prepend (skipped_paths, equal + 1);
     578                 :           0 :           else if (i + 1 < argc)
     579                 :             :             {
     580                 :           0 :               argv[i++] = NULL;
     581                 :           0 :               skipped_paths = g_slist_prepend (skipped_paths, argv[i]);
     582                 :             :             }
     583                 :           0 :           argv[i] = NULL;
     584                 :             :         }
     585                 :           5 :       else if (strcmp ("--test-arg", argv[i]) == 0 || strncmp ("--test-arg=", argv[i], 11) == 0)
     586                 :           1 :         {
     587                 :           1 :           gchar *equal = argv[i] + 10;
     588                 :           1 :           if (*equal == '=')
     589                 :           1 :             subtest_args = g_slist_prepend (subtest_args, equal + 1);
     590                 :           0 :           else if (i + 1 < argc)
     591                 :             :             {
     592                 :           0 :               argv[i++] = NULL;
     593                 :           0 :               subtest_args = g_slist_prepend (subtest_args, argv[i]);
     594                 :             :             }
     595                 :           1 :           argv[i] = NULL;
     596                 :             :         }
     597                 :           4 :       else if (strcmp ("-o", argv[i]) == 0 || strncmp ("-o=", argv[i], 3) == 0)
     598                 :           1 :         {
     599                 :           1 :           gchar *equal = argv[i] + 2;
     600                 :           1 :           if (*equal == '=')
     601                 :           0 :             output_filename = equal + 1;
     602                 :           1 :           else if (i + 1 < argc)
     603                 :             :             {
     604                 :           1 :               argv[i++] = NULL;
     605                 :           1 :               output_filename = argv[i];
     606                 :             :             }
     607                 :           1 :           argv[i] = NULL;
     608                 :             :         }
     609                 :           3 :       else if (strcmp ("-m", argv[i]) == 0 || strncmp ("-m=", argv[i], 3) == 0)
     610                 :           0 :         {
     611                 :           0 :           gchar *equal = argv[i] + 2;
     612                 :           0 :           const gchar *mode = "";
     613                 :           0 :           if (*equal == '=')
     614                 :           0 :             mode = equal + 1;
     615                 :           0 :           else if (i + 1 < argc)
     616                 :             :             {
     617                 :           0 :               argv[i++] = NULL;
     618                 :           0 :               mode = argv[i];
     619                 :             :             }
     620                 :           0 :           if (strcmp (mode, "perf") == 0)
     621                 :           0 :             subtest_mode_perf = TRUE;
     622                 :           0 :           else if (strcmp (mode, "slow") == 0 || strcmp (mode, "thorough") == 0)
     623                 :           0 :             subtest_mode_quick = FALSE;
     624                 :           0 :           else if (strcmp (mode, "quick") == 0)
     625                 :             :             {
     626                 :           0 :               subtest_mode_quick = TRUE;
     627                 :           0 :               subtest_mode_perf = FALSE;
     628                 :             :             }
     629                 :           0 :           else if (strcmp (mode, "undefined") == 0)
     630                 :           0 :             subtest_mode_undefined = TRUE;
     631                 :           0 :           else if (strcmp (mode, "no-undefined") == 0)
     632                 :           0 :             subtest_mode_undefined = FALSE;
     633                 :             :           else
     634                 :           0 :             g_error ("unknown test mode: -m %s", mode);
     635                 :           0 :           argv[i] = NULL;
     636                 :             :         }
     637                 :           3 :       else if (strcmp ("-q", argv[i]) == 0 || strcmp ("--quiet", argv[i]) == 0)
     638                 :             :         {
     639                 :           1 :           gtester_quiet = TRUE;
     640                 :           1 :           gtester_verbose = FALSE;
     641                 :           1 :           argv[i] = NULL;
     642                 :             :         }
     643                 :           2 :       else if (strcmp ("--verbose", argv[i]) == 0)
     644                 :             :         {
     645                 :           0 :           gtester_quiet = FALSE;
     646                 :           0 :           gtester_verbose = TRUE;
     647                 :           0 :           argv[i] = NULL;
     648                 :             :         }
     649                 :           2 :       else if (strcmp ("-l", argv[i]) == 0)
     650                 :             :         {
     651                 :           0 :           gtester_list_tests = TRUE;
     652                 :           0 :           argv[i] = NULL;
     653                 :             :         }
     654                 :           2 :       else if (strcmp ("--seed", argv[i]) == 0 || strncmp ("--seed=", argv[i], 7) == 0)
     655                 :           0 :         {
     656                 :           0 :           gchar *equal = argv[i] + 6;
     657                 :           0 :           if (*equal == '=')
     658                 :           0 :             subtest_seedstr = equal + 1;
     659                 :           0 :           else if (i + 1 < argc)
     660                 :             :             {
     661                 :           0 :               argv[i++] = NULL;
     662                 :           0 :               subtest_seedstr = argv[i];
     663                 :             :             }
     664                 :           0 :           argv[i] = NULL;
     665                 :             :         }
     666                 :           2 :       else if (strcmp ("--i-know-this-is-deprecated", argv[i]) == 0)
     667                 :             :         {
     668                 :           1 :           gtester_ignore_deprecation = TRUE;
     669                 :           1 :           argv[i] = NULL;
     670                 :             :         }
     671                 :             :     }
     672                 :             :   /* collapse argv */
     673                 :           2 :   e = 0;
     674                 :          16 :   for (i = 0; i < argc; i++)
     675                 :          14 :     if (argv[i])
     676                 :             :       {
     677                 :           7 :         argv[e++] = argv[i];
     678                 :           7 :         if (i >= e)
     679                 :           5 :           argv[i] = NULL;
     680                 :             :       }
     681                 :           2 :   *argc_p = e;
     682                 :           2 : }
     683                 :             : 
     684                 :             : int
     685                 :           2 : main (int    argc,
     686                 :             :       char **argv)
     687                 :             : {
     688                 :             :   gint ui;
     689                 :             : 
     690                 :           2 :   g_set_prgname (argv[0]);
     691                 :           2 :   parse_args (&argc, &argv);
     692                 :           2 :   if (gtester_selftest)
     693                 :           1 :     return main_selftest (argc, argv);
     694                 :             : 
     695                 :           1 :   if (argc <= 1)
     696                 :             :     {
     697                 :           0 :       usage (FALSE);
     698                 :           0 :       return 1;
     699                 :             :     }
     700                 :             : 
     701                 :           1 :   if (!gtester_ignore_deprecation)
     702                 :           0 :     g_warning ("Deprecated: Since GLib 2.62, gtester and gtester-report are "
     703                 :             :                "deprecated. Port to TAP.");
     704                 :             : 
     705                 :           1 :   if (output_filename)
     706                 :             :     {
     707                 :             :       int errsv;
     708                 :           1 :       log_fd = g_open (output_filename, O_WRONLY | O_CREAT | O_TRUNC, 0666);
     709                 :           1 :       errsv = errno;
     710                 :           1 :       if (log_fd < 0)
     711                 :           0 :         g_error ("Failed to open log file '%s': %s", output_filename, g_strerror (errsv));
     712                 :             :     }
     713                 :             : 
     714                 :           1 :   test_log_printfe ("<?xml version=\"1.0\"?>\n");
     715                 :           1 :   test_log_printfe ("<!-- Deprecated: Since GLib 2.62, gtester and "
     716                 :             :                     "gtester-report are deprecated. Port to TAP. -->\n");
     717                 :           1 :   test_log_printfe ("%s<gtester>\n", sindent (log_indent));
     718                 :           1 :   log_indent += 2;
     719                 :           2 :   for (ui = 1; ui < argc; ui++)
     720                 :             :     {
     721                 :           1 :       const char *binary = argv[ui];
     722                 :           1 :       launch_test (binary);
     723                 :             :       /* we only get here on success or if !subtest_mode_fatal */
     724                 :             :     }
     725                 :           1 :   log_indent -= 2;
     726                 :           1 :   test_log_printfe ("%s</gtester>\n", sindent (log_indent));
     727                 :             : 
     728                 :           1 :   close (log_fd);
     729                 :             : 
     730                 :           1 :   return testcase_fail_count == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
     731                 :             : }
     732                 :             : 
     733                 :             : static void
     734                 :           1 : fixture_setup (guint        *fix,
     735                 :             :                gconstpointer test_data)
     736                 :             : {
     737                 :           1 :   g_assert_cmphex (*fix, ==, 0);
     738                 :           1 :   *fix = 0xdeadbeef;
     739                 :           1 : }
     740                 :             : static void
     741                 :           1 : fixture_test (guint        *fix,
     742                 :             :               gconstpointer test_data)
     743                 :             : {
     744                 :           1 :   g_assert_cmphex (*fix, ==, 0xdeadbeef);
     745                 :           1 :   g_test_message ("This is a test message API test message.");
     746                 :           1 :   g_test_bug_base ("http://www.example.com/bugtracker/");
     747                 :           1 :   g_test_bug ("123");
     748                 :           1 :   g_test_bug_base ("http://www.example.com/bugtracker?bugnum=%s;cmd=showbug");
     749                 :           1 :   g_test_bug ("456");
     750                 :           1 :   g_test_bug ("https://example.com/no-base-used");
     751                 :           1 : }
     752                 :             : static void
     753                 :           1 : fixture_teardown (guint        *fix,
     754                 :             :                   gconstpointer test_data)
     755                 :             : {
     756                 :           1 :   g_assert_cmphex (*fix, ==, 0xdeadbeef);
     757                 :           1 : }
     758                 :             : 
     759                 :             : static int
     760                 :           1 : main_selftest (int    argc,
     761                 :             :                char **argv)
     762                 :             : {
     763                 :             :   /* gtester main() for --gtester-selftest invocations */
     764                 :           1 :   g_test_init (&argc, &argv, NULL);
     765                 :           1 :   g_test_add ("/gtester/fixture-test", guint, NULL, fixture_setup, fixture_test, fixture_teardown);
     766                 :           1 :   return g_test_run();
     767                 :             : }
        

Generated by: LCOV version 2.0-1