gtestutils.c 64 KB
Newer Older
1
/* GLib testing utilities
2 3
 * Copyright (C) 2007 Imendio AB
 * Authors: Tim Janik, Sven Herzberg
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */
20

Tim Janik's avatar
Tim Janik committed
21
#include "config.h"
22

23
#include "gtestutils.h"
24

25
#include <sys/types.h>
26
#ifdef G_OS_UNIX
27
#include <sys/wait.h>
28
#include <sys/time.h>
29
#include <fcntl.h>
30
#endif
Tim Janik's avatar
Tim Janik committed
31 32
#include <string.h>
#include <stdlib.h>
Matthias Clasen's avatar
Matthias Clasen committed
33
#include <stdio.h>
34
#ifdef HAVE_UNISTD_H
35
#include <unistd.h>
36
#endif
37 38 39
#ifdef G_OS_WIN32
#include <io.h>
#endif
40 41 42 43 44
#include <errno.h>
#include <signal.h>
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h>
#endif /* HAVE_SYS_SELECT_H */
45 46 47 48 49 50

#include "gmain.h"
#include "gpattern.h"
#include "grand.h"
#include "gstrfuncs.h"
#include "gtimer.h"
51
#include "gslice.h"
52

53

54 55 56 57
/* Global variable for storing assertion messages; this is the counterpart to
 * glibc's (private) __abort_msg variable, and allows developers and crash
 * analysis systems like Apport and ABRT to fish out assertion messages from
 * core dumps, instead of having to catch them on screen output. */
58
char *__glib_assert_msg = NULL;
Tim Janik's avatar
Tim Janik committed
59 60 61 62 63 64

/* --- structures --- */
struct GTestCase
{
  gchar  *name;
  guint   fixture_size;
65 66 67 68
  void   (*fixture_setup)    (void*, gconstpointer);
  void   (*fixture_test)     (void*, gconstpointer);
  void   (*fixture_teardown) (void*, gconstpointer);
  gpointer test_data;
Tim Janik's avatar
Tim Janik committed
69 70 71 72 73 74 75
};
struct GTestSuite
{
  gchar  *name;
  GSList *suites;
  GSList *cases;
};
76 77 78 79 80 81 82
typedef struct DestroyEntry DestroyEntry;
struct DestroyEntry
{
  DestroyEntry *next;
  GDestroyNotify destroy_func;
  gpointer       destroy_data;
};
Tim Janik's avatar
Tim Janik committed
83

84
/* --- prototypes --- */
85 86 87 88 89 90 91 92 93
static void     test_run_seed                   (const gchar *rseed);
static void     test_trap_clear                 (void);
static guint8*  g_test_log_dump                 (GTestLogMsg *msg,
                                                 guint       *len);
static void     gtest_default_log_handler       (const gchar    *log_domain,
                                                 GLogLevelFlags  log_level,
                                                 const gchar    *message,
                                                 gpointer        unused_data);

94

Tim Janik's avatar
Tim Janik committed
95
/* --- variables --- */
Tim Janik's avatar
Tim Janik committed
96
static int         test_log_fd = -1;
Tim Janik's avatar
Tim Janik committed
97 98 99
static gboolean    test_mode_fatal = TRUE;
static gboolean    g_test_run_once = TRUE;
static gboolean    test_run_list = FALSE;
Tim Janik's avatar
Tim Janik committed
100 101
static gchar      *test_run_seedstr = NULL;
static GRand      *test_run_rand = NULL;
Tim Janik's avatar
Tim Janik committed
102
static gchar      *test_run_name = "";
Tim Janik's avatar
Tim Janik committed
103
static guint       test_run_forks = 0;
104
static guint       test_run_count = 0;
105
static guint       test_run_success = FALSE;
106
static guint       test_skip_count = 0;
Tim Janik's avatar
Tim Janik committed
107 108
static GTimer     *test_user_timer = NULL;
static double      test_user_stamp = 0;
Tim Janik's avatar
Tim Janik committed
109 110
static GSList     *test_paths = NULL;
static GTestSuite *test_suite_root = NULL;
111 112 113 114
static int         test_trap_last_status = 0;
static int         test_trap_last_pid = 0;
static char       *test_trap_last_stdout = NULL;
static char       *test_trap_last_stderr = NULL;
115
static char       *test_uri_base = NULL;
Tim Janik's avatar
Tim Janik committed
116
static gboolean    test_debug_log = FALSE;
117
static DestroyEntry *test_destroy_queue = NULL;
118
static GTestConfig mutable_test_config_vars = {
119
  FALSE,        /* test_initialized */
120 121 122 123 124
  TRUE,         /* test_quick */
  FALSE,        /* test_perf */
  FALSE,        /* test_verbose */
  FALSE,        /* test_quiet */
};
125
const GTestConfig * const g_test_config_vars = &mutable_test_config_vars;
Tim Janik's avatar
Tim Janik committed
126 127

/* --- functions --- */
Tim Janik's avatar
Tim Janik committed
128 129
const char*
g_test_log_type_name (GTestLogType log_type)
Tim Janik's avatar
Tim Janik committed
130
{
Tim Janik's avatar
Tim Janik committed
131
  switch (log_type)
Tim Janik's avatar
Tim Janik committed
132
    {
133 134
    case G_TEST_LOG_NONE:               return "none";
    case G_TEST_LOG_ERROR:              return "error";
Tim Janik's avatar
Tim Janik committed
135 136
    case G_TEST_LOG_START_BINARY:       return "binary";
    case G_TEST_LOG_LIST_CASE:          return "list";
137
    case G_TEST_LOG_SKIP_CASE:          return "skip";
Tim Janik's avatar
Tim Janik committed
138 139 140 141
    case G_TEST_LOG_START_CASE:         return "start";
    case G_TEST_LOG_STOP_CASE:          return "stop";
    case G_TEST_LOG_MIN_RESULT:         return "minperf";
    case G_TEST_LOG_MAX_RESULT:         return "maxperf";
142
    case G_TEST_LOG_MESSAGE:            return "message";
Tim Janik's avatar
Tim Janik committed
143
    }
144
  return "???";
Tim Janik's avatar
Tim Janik committed
145 146 147
}

static void
148 149 150
g_test_log_send (guint         n_bytes,
                 const guint8 *buffer)
{
Tim Janik's avatar
Tim Janik committed
151 152 153 154 155 156 157
  if (test_log_fd >= 0)
    {
      int r;
      do
        r = write (test_log_fd, buffer, n_bytes);
      while (r < 0 && errno == EINTR);
    }
158 159
  if (test_debug_log)
    {
160
      GTestLogBuffer *lbuffer = g_test_log_buffer_new ();
161 162 163 164
      GTestLogMsg *msg;
      guint ui;
      g_test_log_buffer_push (lbuffer, n_bytes, buffer);
      msg = g_test_log_buffer_pop (lbuffer);
165 166
      g_warn_if_fail (msg != NULL);
      g_warn_if_fail (lbuffer->data->len == 0);
167 168
      g_test_log_buffer_free (lbuffer);
      /* print message */
Tim Janik's avatar
Tim Janik committed
169
      g_printerr ("{*LOG(%s)", g_test_log_type_name (msg->log_type));
170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
      for (ui = 0; ui < msg->n_strings; ui++)
        g_printerr (":{%s}", msg->strings[ui]);
      if (msg->n_nums)
        {
          g_printerr (":(");
          for (ui = 0; ui < msg->n_nums; ui++)
            g_printerr ("%s%.16Lg", ui ? ";" : "", msg->nums[ui]);
          g_printerr (")");
        }
      g_printerr (":LOG*}\n");
      g_test_log_msg_free (msg);
    }
}

static void
g_test_log (GTestLogType lbit,
Tim Janik's avatar
Tim Janik committed
186 187 188 189 190 191
            const gchar *string1,
            const gchar *string2,
            guint        n_args,
            long double *largs)
{
  gboolean fail = lbit == G_TEST_LOG_STOP_CASE && largs[0] != 0;
192 193 194 195
  GTestLogMsg msg;
  gchar *astrings[3] = { NULL, NULL, NULL };
  guint8 *dbuffer;
  guint32 dbufferlen;
Tim Janik's avatar
Tim Janik committed
196 197 198

  switch (lbit)
    {
199 200 201 202
    case G_TEST_LOG_START_BINARY:
      if (g_test_verbose())
        g_print ("GTest: random seed: %s\n", string2);
      break;
Tim Janik's avatar
Tim Janik committed
203
    case G_TEST_LOG_STOP_CASE:
204 205 206
      if (g_test_verbose())
        g_print ("GTest: result: %s\n", fail ? "FAIL" : "OK");
      else if (!g_test_quiet())
Tim Janik's avatar
Tim Janik committed
207 208 209 210 211
        g_print ("%s\n", fail ? "FAIL" : "OK");
      if (fail && test_mode_fatal)
        abort();
      break;
    case G_TEST_LOG_MIN_RESULT:
212
      if (g_test_verbose())
Tim Janik's avatar
Tim Janik committed
213 214 215
        g_print ("(MINPERF:%s)\n", string1);
      break;
    case G_TEST_LOG_MAX_RESULT:
216
      if (g_test_verbose())
Tim Janik's avatar
Tim Janik committed
217 218
        g_print ("(MAXPERF:%s)\n", string1);
      break;
219 220 221 222
    case G_TEST_LOG_MESSAGE:
      if (g_test_verbose())
        g_print ("(MSG: %s)\n", string1);
      break;
Tim Janik's avatar
Tim Janik committed
223 224 225
    default: ;
    }

226 227 228 229 230 231 232 233 234 235
  msg.log_type = lbit;
  msg.n_strings = (string1 != NULL) + (string1 && string2);
  msg.strings = astrings;
  astrings[0] = (gchar*) string1;
  astrings[1] = astrings[0] ? (gchar*) string2 : NULL;
  msg.n_nums = n_args;
  msg.nums = largs;
  dbuffer = g_test_log_dump (&msg, &dbufferlen);
  g_test_log_send (dbufferlen, dbuffer);
  g_free (dbuffer);
Tim Janik's avatar
Tim Janik committed
236 237 238 239

  switch (lbit)
    {
    case G_TEST_LOG_START_CASE:
240 241 242
      if (g_test_verbose())
        g_print ("GTest: run: %s\n", string1);
      else if (!g_test_quiet())
Tim Janik's avatar
Tim Janik committed
243 244 245 246 247 248
        g_print ("%s: ", string1);
      break;
    default: ;
    }
}

249 250 251
/* We intentionally parse the command line without GOptionContext
 * because otherwise you would never be able to test it.
 */
Tim Janik's avatar
Tim Janik committed
252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274
static void
parse_args (gint    *argc_p,
            gchar ***argv_p)
{
  guint argc = *argc_p;
  gchar **argv = *argv_p;
  guint i, e;
  /* parse known args */
  for (i = 1; i < argc; i++)
    {
      if (strcmp (argv[i], "--g-fatal-warnings") == 0)
        {
          GLogLevelFlags fatal_mask = (GLogLevelFlags) g_log_set_always_fatal ((GLogLevelFlags) G_LOG_FATAL_MASK);
          fatal_mask = (GLogLevelFlags) (fatal_mask | G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL);
          g_log_set_always_fatal (fatal_mask);
          argv[i] = NULL;
        }
      else if (strcmp (argv[i], "--keep-going") == 0 ||
               strcmp (argv[i], "-k") == 0)
        {
          test_mode_fatal = FALSE;
          argv[i] = NULL;
        }
Tim Janik's avatar
Tim Janik committed
275 276 277 278 279
      else if (strcmp (argv[i], "--debug-log") == 0)
        {
          test_debug_log = TRUE;
          argv[i] = NULL;
        }
Tim Janik's avatar
Tim Janik committed
280
      else if (strcmp ("--GTestLogFD", argv[i]) == 0 || strncmp ("--GTestLogFD=", argv[i], 13) == 0)
Tim Janik's avatar
Tim Janik committed
281
        {
Tim Janik's avatar
Tim Janik committed
282
          gchar *equal = argv[i] + 12;
Tim Janik's avatar
Tim Janik committed
283
          if (*equal == '=')
Tim Janik's avatar
Tim Janik committed
284
            test_log_fd = g_ascii_strtoull (equal + 1, NULL, 0);
Tim Janik's avatar
Tim Janik committed
285 286 287
          else if (i + 1 < argc)
            {
              argv[i++] = NULL;
Tim Janik's avatar
Tim Janik committed
288
              test_log_fd = g_ascii_strtoull (argv[i], NULL, 0);
Tim Janik's avatar
Tim Janik committed
289 290 291
            }
          argv[i] = NULL;
        }
292 293 294 295 296 297 298 299 300 301 302 303
      else if (strcmp ("--GTestSkipCount", argv[i]) == 0 || strncmp ("--GTestSkipCount=", argv[i], 17) == 0)
        {
          gchar *equal = argv[i] + 16;
          if (*equal == '=')
            test_skip_count = g_ascii_strtoull (equal + 1, NULL, 0);
          else if (i + 1 < argc)
            {
              argv[i++] = NULL;
              test_skip_count = g_ascii_strtoull (argv[i], NULL, 0);
            }
          argv[i] = NULL;
        }
Tim Janik's avatar
Tim Janik committed
304
      else if (strcmp ("-p", argv[i]) == 0 || strncmp ("-p=", argv[i], 3) == 0)
Tim Janik's avatar
Tim Janik committed
305 306 307
        {
          gchar *equal = argv[i] + 2;
          if (*equal == '=')
Tim Janik's avatar
Tim Janik committed
308
            test_paths = g_slist_prepend (test_paths, equal + 1);
Tim Janik's avatar
Tim Janik committed
309 310 311
          else if (i + 1 < argc)
            {
              argv[i++] = NULL;
Tim Janik's avatar
Tim Janik committed
312
              test_paths = g_slist_prepend (test_paths, argv[i]);
Tim Janik's avatar
Tim Janik committed
313 314 315 316 317 318 319 320 321 322 323 324 325 326 327
            }
          argv[i] = NULL;
        }
      else if (strcmp ("-m", argv[i]) == 0 || strncmp ("-m=", argv[i], 3) == 0)
        {
          gchar *equal = argv[i] + 2;
          const gchar *mode = "";
          if (*equal == '=')
            mode = equal + 1;
          else if (i + 1 < argc)
            {
              argv[i++] = NULL;
              mode = argv[i];
            }
          if (strcmp (mode, "perf") == 0)
328
            mutable_test_config_vars.test_perf = TRUE;
Tim Janik's avatar
Tim Janik committed
329
          else if (strcmp (mode, "slow") == 0)
330
            mutable_test_config_vars.test_quick = FALSE;
331 332
          else if (strcmp (mode, "thorough") == 0)
            mutable_test_config_vars.test_quick = FALSE;
Tim Janik's avatar
Tim Janik committed
333 334
          else if (strcmp (mode, "quick") == 0)
            {
335 336
              mutable_test_config_vars.test_quick = TRUE;
              mutable_test_config_vars.test_perf = FALSE;
Tim Janik's avatar
Tim Janik committed
337 338 339 340 341 342 343
            }
          else
            g_error ("unknown test mode: -m %s", mode);
          argv[i] = NULL;
        }
      else if (strcmp ("-q", argv[i]) == 0 || strcmp ("--quiet", argv[i]) == 0)
        {
344 345
          mutable_test_config_vars.test_quiet = TRUE;
          mutable_test_config_vars.test_verbose = FALSE;
Tim Janik's avatar
Tim Janik committed
346 347 348 349
          argv[i] = NULL;
        }
      else if (strcmp ("--verbose", argv[i]) == 0)
        {
350 351
          mutable_test_config_vars.test_quiet = FALSE;
          mutable_test_config_vars.test_verbose = TRUE;
Tim Janik's avatar
Tim Janik committed
352 353 354 355 356 357 358
          argv[i] = NULL;
        }
      else if (strcmp ("-l", argv[i]) == 0)
        {
          test_run_list = TRUE;
          argv[i] = NULL;
        }
Tim Janik's avatar
Tim Janik committed
359
      else if (strcmp ("--seed", argv[i]) == 0 || strncmp ("--seed=", argv[i], 7) == 0)
Tim Janik's avatar
Tim Janik committed
360
        {
Tim Janik's avatar
Tim Janik committed
361
          gchar *equal = argv[i] + 6;
Tim Janik's avatar
Tim Janik committed
362
          if (*equal == '=')
Tim Janik's avatar
Tim Janik committed
363
            test_run_seedstr = equal + 1;
Tim Janik's avatar
Tim Janik committed
364 365 366
          else if (i + 1 < argc)
            {
              argv[i++] = NULL;
Tim Janik's avatar
Tim Janik committed
367
              test_run_seedstr = argv[i];
Tim Janik's avatar
Tim Janik committed
368 369 370
            }
          argv[i] = NULL;
        }
371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391
      else if (strcmp ("-?", argv[i]) == 0 || strcmp ("--help", argv[i]) == 0)
        {
          printf ("Usage:\n"
                  "  %s [OPTION...]\n\n"
                  "Help Options:\n"
                  "  -?, --help                     Show help options\n"
                  "Test Options:\n"
                  "  -l                             List test cases available in a test executable\n"
                  "  -seed=RANDOMSEED               Provide a random seed to reproduce test\n"
                  "                                 runs using random numbers\n"
                  "  --verbose                      Run tests verbosely\n"
                  "  -q, --quiet                    Run tests quietly\n"
                  "  -p TESTPATH                    execute all tests matching TESTPATH\n"
                  "  -m {perf|slow|thorough|quick}  Execute tests according modes\n"
                  "  --debug-log                    debug test logging output\n"
                  "  -k, --keep-going               gtester-specific argument\n"
                  "  --GTestLogFD=N                 gtester-specific argument\n"
                  "  --GTestSkipCount=N             gtester-specific argument\n",
                  argv[0]);
          exit (0);
        }
Tim Janik's avatar
Tim Janik committed
392 393 394 395 396 397 398 399 400 401 402 403 404
    }
  /* collapse argv */
  e = 1;
  for (i = 1; i < argc; i++)
    if (argv[i])
      {
        argv[e++] = argv[i];
        if (i >= e)
          argv[i] = NULL;
      }
  *argc_p = e;
}

405 406 407 408 409 410
/**
 * g_test_init:
 * @argc: Address of the @argc parameter of the main() function.
 *        Changed if any arguments were handled.
 * @argv: Address of the @argv parameter of main().
 *        Any parameters understood by g_test_init() stripped before return.
411
 * @...: Reserved for future extension. Currently, you must pass %NULL.
412 413 414 415 416
 *
 * Initialize the GLib testing framework, e.g. by seeding the
 * test random number generator, the name for g_get_prgname()
 * and parsing test related command line args.
 * So far, the following arguments are understood:
Matthias Clasen's avatar
Matthias Clasen committed
417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487
 * <variablelist>
 *   <varlistentry>
 *     <term><option>-l</option></term>
 *     <listitem><para>
 *       list test cases available in a test executable.
 *     </para></listitem>
 *   </varlistentry>
 *   <varlistentry>
 *     <term><option>--seed=<replaceable>RANDOMSEED</replaceable></option></term>
 *     <listitem><para>
 *       provide a random seed to reproduce test runs using random numbers.
 *     </para></listitem>
 *     </varlistentry>
 *     <varlistentry>
 *       <term><option>--verbose</option></term>
 *       <listitem><para>run tests verbosely.</para></listitem>
 *     </varlistentry>
 *     <varlistentry>
 *       <term><option>-q</option>, <option>--quiet</option></term>
 *       <listitem><para>run tests quietly.</para></listitem>
 *     </varlistentry>
 *     <varlistentry>
 *       <term><option>-p <replaceable>TESTPATH</replaceable></option></term>
 *       <listitem><para>
 *         execute all tests matching <replaceable>TESTPATH</replaceable>.
 *       </para></listitem>
 *     </varlistentry>
 *     <varlistentry>
 *       <term><option>-m {perf|slow|thorough|quick}</option></term>
 *       <listitem><para>
 *         execute tests according to these test modes:
 *         <variablelist>
 *           <varlistentry>
 *             <term>perf</term>
 *             <listitem><para>
 *               performance tests, may take long and report results.
 *             </para></listitem>
 *           </varlistentry>
 *           <varlistentry>
 *             <term>slow, thorough</term>
 *             <listitem><para>
 *               slow and thorough tests, may take quite long and 
 *               maximize coverage.
 *             </para></listitem>
 *           </varlistentry>
 *           <varlistentry>
 *             <term>quick</term>
 *             <listitem><para>
 *               quick tests, should run really quickly and give good coverage.
 *             </para></listitem>
 *           </varlistentry>
 *         </variablelist>
 *       </para></listitem>
 *     </varlistentry>
 *     <varlistentry>
 *       <term><option>--debug-log</option></term>
 *       <listitem><para>debug test logging output.</para></listitem>
 *     </varlistentry>
 *     <varlistentry>
 *       <term><option>-k</option>, <option>--keep-going</option></term>
 *       <listitem><para>gtester-specific argument.</para></listitem>
 *     </varlistentry>
 *     <varlistentry>
 *       <term><option>--GTestLogFD <replaceable>N</replaceable></option></term>
 *       <listitem><para>gtester-specific argument.</para></listitem>
 *     </varlistentry>
 *     <varlistentry>
 *       <term><option>--GTestSkipCount <replaceable>N</replaceable></option></term>
 *       <listitem><para>gtester-specific argument.</para></listitem>
 *     </varlistentry>
 *  </variablelist>
488 489
 *
 * Since: 2.16
490
 */
Tim Janik's avatar
Tim Janik committed
491
void
492 493
g_test_init (int    *argc,
             char ***argv,
Tim Janik's avatar
Tim Janik committed
494 495
             ...)
{
Tim Janik's avatar
Tim Janik committed
496
  static char seedstr[4 + 4 * 8 + 1];
Tim Janik's avatar
Tim Janik committed
497 498
  va_list args;
  gpointer vararg1;
499 500 501
  /* make warnings and criticals fatal for all test programs */
  GLogLevelFlags fatal_mask = (GLogLevelFlags) g_log_set_always_fatal ((GLogLevelFlags) G_LOG_FATAL_MASK);
  fatal_mask = (GLogLevelFlags) (fatal_mask | G_LOG_LEVEL_WARNING | G_LOG_LEVEL_CRITICAL);
502
  g_log_set_always_fatal (fatal_mask);
503
  /* check caller args */
Tim Janik's avatar
Tim Janik committed
504 505
  g_return_if_fail (argc != NULL);
  g_return_if_fail (argv != NULL);
506 507
  g_return_if_fail (g_test_config_vars->test_initialized == FALSE);
  mutable_test_config_vars.test_initialized = TRUE;
Tim Janik's avatar
Tim Janik committed
508 509 510 511 512 513

  va_start (args, argv);
  vararg1 = va_arg (args, gpointer); /* reserved for future extensions */
  va_end (args);
  g_return_if_fail (vararg1 == NULL);

Tim Janik's avatar
Tim Janik committed
514 515 516 517 518
  /* setup random seed string */
  g_snprintf (seedstr, sizeof (seedstr), "R02S%08x%08x%08x%08x", g_random_int(), g_random_int(), g_random_int(), g_random_int());
  test_run_seedstr = seedstr;

  /* parse args, sets up mode, changes seed, etc. */
Tim Janik's avatar
Tim Janik committed
519
  parse_args (argc, argv);
Tim Janik's avatar
Tim Janik committed
520 521
  if (!g_get_prgname())
    g_set_prgname ((*argv)[0]);
Tim Janik's avatar
Tim Janik committed
522

Tim Janik's avatar
Tim Janik committed
523 524 525 526 527
  /* verify GRand reliability, needed for reliable seeds */
  if (1)
    {
      GRand *rg = g_rand_new_with_seed (0xc8c49fb6);
      guint32 t1 = g_rand_int (rg), t2 = g_rand_int (rg), t3 = g_rand_int (rg), t4 = g_rand_int (rg);
528
      /* g_print ("GRand-current: 0x%x 0x%x 0x%x 0x%x\n", t1, t2, t3, t4); */
Tim Janik's avatar
Tim Janik committed
529 530 531 532
      if (t1 != 0xfab39f9b || t2 != 0xb948fb0e || t3 != 0x3d31be26 || t4 != 0x43a19d66)
        g_warning ("random numbers are not GRand-2.2 compatible, seeds may be broken (check $G_RANDOM_VERSION)");
      g_rand_free (rg);
    }
Tim Janik's avatar
Tim Janik committed
533

Tim Janik's avatar
Tim Janik committed
534 535
  /* check rand seed */
  test_run_seed (test_run_seedstr);
Tim Janik's avatar
Tim Janik committed
536

Tim Janik's avatar
Tim Janik committed
537
  /* report program start */
538
  g_log_set_default_handler (gtest_default_log_handler, NULL);
Tim Janik's avatar
Tim Janik committed
539
  g_test_log (G_TEST_LOG_START_BINARY, g_get_prgname(), test_run_seedstr, 0, NULL);
Tim Janik's avatar
Tim Janik committed
540 541 542 543 544 545 546 547 548 549 550
}

static void
test_run_seed (const gchar *rseed)
{
  guint seed_failed = 0;
  if (test_run_rand)
    g_rand_free (test_run_rand);
  test_run_rand = NULL;
  while (strchr (" \t\v\r\n\f", *rseed))
    rseed++;
551
  if (strncmp (rseed, "R02S", 4) == 0)  /* seed for random generator 02 (GRand-2.2) */
Tim Janik's avatar
Tim Janik committed
552 553
    {
      const char *s = rseed + 4;
554
      if (strlen (s) >= 32)             /* require 4 * 8 chars */
Tim Janik's avatar
Tim Janik committed
555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579
        {
          guint32 seedarray[4];
          gchar *p, hexbuf[9] = { 0, };
          memcpy (hexbuf, s + 0, 8);
          seedarray[0] = g_ascii_strtoull (hexbuf, &p, 16);
          seed_failed += p != NULL && *p != 0;
          memcpy (hexbuf, s + 8, 8);
          seedarray[1] = g_ascii_strtoull (hexbuf, &p, 16);
          seed_failed += p != NULL && *p != 0;
          memcpy (hexbuf, s + 16, 8);
          seedarray[2] = g_ascii_strtoull (hexbuf, &p, 16);
          seed_failed += p != NULL && *p != 0;
          memcpy (hexbuf, s + 24, 8);
          seedarray[3] = g_ascii_strtoull (hexbuf, &p, 16);
          seed_failed += p != NULL && *p != 0;
          if (!seed_failed)
            {
              test_run_rand = g_rand_new_with_seed_array (seedarray, 4);
              return;
            }
        }
    }
  g_error ("Unknown or invalid random seed: %s", rseed);
}

580 581 582
/**
 * g_test_rand_int:
 *
583
 * Get a reproducible random integer number.
Matthias Clasen's avatar
Matthias Clasen committed
584
 *
585
 * The random numbers generated by the g_test_rand_*() family of functions
586 587
 * change with every new test program start, unless the --seed option is
 * given when starting test programs.
Matthias Clasen's avatar
Matthias Clasen committed
588
 *
589 590 591 592 593
 * For individual test cases however, the random number generator is
 * reseeded, to avoid dependencies between tests and to make --seed
 * effective for all test cases.
 *
 * Returns: a random number from the seeded random number generator.
594 595
 *
 * Since: 2.16
596
 */
Tim Janik's avatar
Tim Janik committed
597 598 599 600 601 602
gint32
g_test_rand_int (void)
{
  return g_rand_int (test_run_rand);
}

603 604 605 606 607
/**
 * g_test_rand_int_range:
 * @begin: the minimum value returned by this function
 * @end:   the smallest value not to be returned by this function
 *
608
 * Get a reproducible random integer number out of a specified range,
609 610
 * see g_test_rand_int() for details on test case random numbers.
 *
611
 * Returns: a number with @begin <= number < @end.
612 613
 * 
 * Since: 2.16
614
 */
Tim Janik's avatar
Tim Janik committed
615 616 617 618 619 620 621
gint32
g_test_rand_int_range (gint32          begin,
                       gint32          end)
{
  return g_rand_int_range (test_run_rand, begin, end);
}

622 623 624
/**
 * g_test_rand_double:
 *
625
 * Get a reproducible random floating point number,
626 627
 * see g_test_rand_int() for details on test case random numbers.
 *
Matthias Clasen's avatar
Matthias Clasen committed
628
 * Returns: a random number from the seeded random number generator.
629 630
 *
 * Since: 2.16
631
 */
Tim Janik's avatar
Tim Janik committed
632 633 634 635 636 637
double
g_test_rand_double (void)
{
  return g_rand_double (test_run_rand);
}

638 639 640 641 642
/**
 * g_test_rand_double_range:
 * @range_start: the minimum value returned by this function
 * @range_end: the minimum value not returned by this function
 *
643
 * Get a reproducible random floating pointer number out of a specified range,
644 645
 * see g_test_rand_int() for details on test case random numbers.
 *
646
 * Returns: a number with @range_start <= number < @range_end.
647 648
 *
 * Since: 2.16
649
 */
Tim Janik's avatar
Tim Janik committed
650 651 652 653 654
double
g_test_rand_double_range (double          range_start,
                          double          range_end)
{
  return g_rand_double_range (test_run_rand, range_start, range_end);
Tim Janik's avatar
Tim Janik committed
655 656
}

657 658 659 660 661
/**
 * g_test_timer_start:
 *
 * Start a timing test. Call g_test_timer_elapsed() when the task is supposed
 * to be done. Call this function again to restart the timer.
662 663
 *
 * Since: 2.16
664
 */
Tim Janik's avatar
Tim Janik committed
665 666 667 668 669 670 671 672 673
void
g_test_timer_start (void)
{
  if (!test_user_timer)
    test_user_timer = g_timer_new();
  test_user_stamp = 0;
  g_timer_start (test_user_timer);
}

674 675 676 677
/**
 * g_test_timer_elapsed:
 *
 * Get the time since the last start of the timer with g_test_timer_start().
678 679
 *
 * Returns: the time since the last start of the timer, as a double
680 681
 *
 * Since: 2.16
682
 */
Tim Janik's avatar
Tim Janik committed
683 684 685 686 687 688 689
double
g_test_timer_elapsed (void)
{
  test_user_stamp = test_user_timer ? g_timer_elapsed (test_user_timer, NULL) : 0;
  return test_user_stamp;
}

690 691 692 693
/**
 * g_test_timer_last:
 *
 * Report the last result of g_test_timer_elapsed().
694 695
 *
 * Returns: the last result of g_test_timer_elapsed(), as a double
696 697
 *
 * Since: 2.16
698
 */
Tim Janik's avatar
Tim Janik committed
699 700 701 702 703 704
double
g_test_timer_last (void)
{
  return test_user_stamp;
}

705 706 707 708
/**
 * g_test_minimized_result:
 * @minimized_quantity: the reported value
 * @format: the format string of the report message
709
 * @...: arguments to pass to the printf() function
710 711 712 713 714 715
 *
 * Report the result of a performance or measurement test.
 * The test should generally strive to minimize the reported
 * quantities (smaller values are better than larger ones),
 * this and @minimized_quantity can determine sorting
 * order for test result reports.
716 717
 *
 * Since: 2.16
718
 */
Tim Janik's avatar
Tim Janik committed
719 720 721 722 723 724 725 726
void
g_test_minimized_result (double          minimized_quantity,
                         const char     *format,
                         ...)
{
  long double largs = minimized_quantity;
  gchar *buffer;
  va_list args;
727

Tim Janik's avatar
Tim Janik committed
728 729 730
  va_start (args, format);
  buffer = g_strdup_vprintf (format, args);
  va_end (args);
731

Tim Janik's avatar
Tim Janik committed
732 733 734 735
  g_test_log (G_TEST_LOG_MIN_RESULT, buffer, NULL, 1, &largs);
  g_free (buffer);
}

736
/**
737
 * g_test_maximized_result:
738 739
 * @maximized_quantity: the reported value
 * @format: the format string of the report message
740
 * @...: arguments to pass to the printf() function
741 742 743 744 745 746
 *
 * Report the result of a performance or measurement test.
 * The test should generally strive to maximize the reported
 * quantities (larger values are better than smaller ones),
 * this and @maximized_quantity can determine sorting
 * order for test result reports.
747 748
 *
 * Since: 2.16
749
 */
Tim Janik's avatar
Tim Janik committed
750 751 752 753 754 755 756 757
void
g_test_maximized_result (double          maximized_quantity,
                         const char     *format,
                         ...)
{
  long double largs = maximized_quantity;
  gchar *buffer;
  va_list args;
758

Tim Janik's avatar
Tim Janik committed
759 760 761
  va_start (args, format);
  buffer = g_strdup_vprintf (format, args);
  va_end (args);
762

Tim Janik's avatar
Tim Janik committed
763 764 765 766
  g_test_log (G_TEST_LOG_MAX_RESULT, buffer, NULL, 1, &largs);
  g_free (buffer);
}

767 768 769 770 771 772
/**
 * g_test_message:
 * @format: the format string
 * @...:    printf-like arguments to @format
 *
 * Add a message to the test report.
773 774
 *
 * Since: 2.16
775
 */
776 777 778 779 780 781
void
g_test_message (const char *format,
                ...)
{
  gchar *buffer;
  va_list args;
782

783 784 785
  va_start (args, format);
  buffer = g_strdup_vprintf (format, args);
  va_end (args);
786

787 788 789 790
  g_test_log (G_TEST_LOG_MESSAGE, buffer, NULL, 0, NULL);
  g_free (buffer);
}

791 792 793 794 795
/**
 * g_test_bug_base:
 * @uri_pattern: the base pattern for bug URIs
 *
 * Specify the base URI for bug reports.
Matthias Clasen's avatar
Matthias Clasen committed
796
 *
797 798 799 800 801 802 803 804
 * The base URI is used to construct bug report messages for
 * g_test_message() when g_test_bug() is called.
 * Calling this function outside of a test case sets the
 * default base URI for all test cases. Calling it from within
 * a test case changes the base URI for the scope of the test
 * case only.
 * Bug URIs are constructed by appending a bug specific URI
 * portion to @uri_pattern, or by replacing the special string
Allison Karlitskaya's avatar
Allison Karlitskaya committed
805
 * '\%s' within @uri_pattern if that is present.
806 807
 *
 * Since: 2.16
808
 */
809 810 811 812 813 814 815
void
g_test_bug_base (const char *uri_pattern)
{
  g_free (test_uri_base);
  test_uri_base = g_strdup (uri_pattern);
}

816 817 818 819 820 821 822 823
/**
 * g_test_bug:
 * @bug_uri_snippet: Bug specific bug tracker URI portion.
 *
 * This function adds a message to test reports that
 * associates a bug URI with a test case.
 * Bug URIs are constructed from a base URI set with g_test_bug_base()
 * and @bug_uri_snippet.
824 825
 *
 * Since: 2.16
826
 */
827 828 829 830
void
g_test_bug (const char *bug_uri_snippet)
{
  char *c;
831

832 833
  g_return_if_fail (test_uri_base != NULL);
  g_return_if_fail (bug_uri_snippet != NULL);
834

835 836 837 838 839 840 841 842 843 844 845 846 847
  c = strstr (test_uri_base, "%s");
  if (c)
    {
      char *b = g_strndup (test_uri_base, c - test_uri_base);
      char *s = g_strconcat (b, bug_uri_snippet, c + 2, NULL);
      g_free (b);
      g_test_message ("Bug Reference: %s", s);
      g_free (s);
    }
  else
    g_test_message ("Bug Reference: %s%s", test_uri_base, bug_uri_snippet);
}

848 849 850 851 852 853
/**
 * g_test_get_root:
 *
 * Get the toplevel test suite for the test path API.
 *
 * Returns: the toplevel #GTestSuite
854 855
 *
 * Since: 2.16
856
 */
Tim Janik's avatar
Tim Janik committed
857 858 859 860 861 862 863 864 865
GTestSuite*
g_test_get_root (void)
{
  if (!test_suite_root)
    {
      test_suite_root = g_test_create_suite ("root");
      g_free (test_suite_root->name);
      test_suite_root->name = g_strdup ("");
    }
866

Tim Janik's avatar
Tim Janik committed
867 868 869
  return test_suite_root;
}

870 871 872 873 874 875
/**
 * g_test_run:
 *
 * Runs all tests under the toplevel suite which can be retrieved
 * with g_test_get_root(). Similar to g_test_run_suite(), the test
 * cases to be run are filtered according to
Matthias Clasen's avatar
Matthias Clasen committed
876 877
 * test path arguments (-p <replaceable>testpath</replaceable>) as 
 * parsed by g_test_init().
878 879
 * g_test_run_suite() or g_test_run() may only be called once
 * in a program.
880 881
 *
 * Returns: 0 on success
882 883
 *
 * Since: 2.16
884
 */
Tim Janik's avatar
Tim Janik committed
885 886 887 888 889 890
int
g_test_run (void)
{
  return g_test_run_suite (g_test_get_root());
}

891 892 893 894
/**
 * g_test_create_case:
 * @test_name:     the name for the test case
 * @data_size:     the size of the fixture data structure
895
 * @test_data:     test data argument for the test functions
896 897 898 899 900 901 902 903 904 905 906 907
 * @data_setup:    the function to set up the fixture data
 * @data_test:     the actual test function
 * @data_teardown: the function to teardown the fixture data
 *
 * Create a new #GTestCase, named @test_name, this API is fairly
 * low level, calling g_test_add() or g_test_add_func() is preferable.
 * When this test is executed, a fixture structure of size @data_size
 * will be allocated and filled with 0s. Then data_setup() is called
 * to initialize the fixture. After fixture setup, the actual test
 * function data_test() is called. Once the test run completed, the
 * fixture structure is torn down  by calling data_teardown() and
 * after that the memory is released.
908
 *
909 910 911 912 913 914
 * Splitting up a test run into fixture setup, test function and
 * fixture teardown is most usful if the same fixture is used for
 * multiple tests. In this cases, g_test_create_case() will be
 * called with the same fixture, but varying @test_name and
 * @data_test arguments.
 *
915
 * Returns: a newly allocated #GTestCase.
916 917
 *
 * Since: 2.16
918
 */
Tim Janik's avatar
Tim Janik committed
919
GTestCase*
920 921 922 923 924 925
g_test_create_case (const char       *test_name,
                    gsize             data_size,
                    gconstpointer     test_data,
                    GTestFixtureFunc  data_setup,
                    GTestFixtureFunc  data_test,
                    GTestFixtureFunc  data_teardown)
Tim Janik's avatar
Tim Janik committed
926
{
927
  GTestCase *tc;
928

Tim Janik's avatar
Tim Janik committed
929 930 931 932
  g_return_val_if_fail (test_name != NULL, NULL);
  g_return_val_if_fail (strchr (test_name, '/') == NULL, NULL);
  g_return_val_if_fail (test_name[0] != 0, NULL);
  g_return_val_if_fail (data_test != NULL, NULL);
933

934
  tc = g_slice_new0 (GTestCase);
Tim Janik's avatar
Tim Janik committed
935
  tc->name = g_strdup (test_name);
936
  tc->test_data = (gpointer) test_data;
Tim Janik's avatar
Tim Janik committed
937 938 939 940
  tc->fixture_size = data_size;
  tc->fixture_setup = (void*) data_setup;
  tc->fixture_test = (void*) data_test;
  tc->fixture_teardown = (void*) data_teardown;
941

Tim Janik's avatar
Tim Janik committed
942 943 944
  return tc;
}

945 946 947 948 949 950 951 952 953 954 955 956 957 958 959
/**
 * GTestFixtureFunc:
 * @fixture: the test fixture
 * @user_data: the data provided when registering the test
 *
 * The type used for functions that operate on test fixtures.  This is
 * used for the fixture setup and teardown functions as well as for the
 * testcases themselves.
 *
 * @user_data is a pointer to the data that was given when registering
 * the test case.
 *
 * @fixture will be a pointer to the area of memory allocated by the
 * test framework, of the size requested.  If the requested size was
 * zero then @fixture will be equal to @user_data.
Matthias Clasen's avatar
Matthias Clasen committed
960 961 962
 *
 * Since: 2.28
 */
Tim Janik's avatar
Tim Janik committed
963
void
964 965 966 967 968 969
g_test_add_vtable (const char       *testpath,
                   gsize             data_size,
                   gconstpointer     test_data,
                   GTestFixtureFunc  data_setup,
                   GTestFixtureFunc  fixture_test_func,
                   GTestFixtureFunc  data_teardown)
Tim Janik's avatar
Tim Janik committed
970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987
{
  gchar **segments;
  guint ui;
  GTestSuite *suite;

  g_return_if_fail (testpath != NULL);
  g_return_if_fail (testpath[0] == '/');
  g_return_if_fail (fixture_test_func != NULL);

  suite = g_test_get_root();
  segments = g_strsplit (testpath, "/", -1);
  for (ui = 0; segments[ui] != NULL; ui++)
    {
      const char *seg = segments[ui];
      gboolean islast = segments[ui + 1] == NULL;
      if (islast && !seg[0])
        g_error ("invalid test case path: %s", testpath);
      else if (!seg[0])
988
        continue;       /* initial or duplicate slash */
Tim Janik's avatar
Tim Janik committed
989 990 991 992 993 994 995 996
      else if (!islast)
        {
          GTestSuite *csuite = g_test_create_suite (seg);
          g_test_suite_add_suite (suite, csuite);
          suite = csuite;
        }
      else /* islast */
        {
997
          GTestCase *tc = g_test_create_case (seg, data_size, test_data, data_setup, fixture_test_func, data_teardown);
Tim Janik's avatar
Tim Janik committed
998 999 1000 1001 1002 1003
          g_test_suite_add (suite, tc);
        }
    }
  g_strfreev (segments);
}

1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020
/**
 * g_test_fail:
 *
 * Indicates that a test failed. This function can be called
 * multiple times from the same test. You can use this function
 * if your test failed in a recoverable way.
 * 
 * Do not use this function if the failure of a test could cause
 * other tests to malfunction.
 *
 * Calling this function will not stop the test from running, you
 * need to return from the test function yourself. So you can
 * produce additional diagnostic messages or even continue running
 * the test.
 *
 * If not called from inside a test, this function does nothing.
 *
1021
 * Since: 2.30
1022 1023 1024 1025 1026 1027 1028
 **/
void
g_test_fail (void)
{
  test_run_success = FALSE;
}

1029 1030 1031 1032
/**
 * GTestFunc:
 *
 * The type used for test case functions.
Matthias Clasen's avatar
Matthias Clasen committed
1033 1034 1035 1036
 *
 * Since: 2.28
 */

1037 1038
/**
 * g_test_add_func:
1039
 * @testpath:   Slash-separated test case path name for the test.
1040 1041 1042 1043 1044
 * @test_func:  The test function to invoke for this test.
 *
 * Create a new test case, similar to g_test_create_case(). However
 * the test is assumed to use no fixture, and test suites are automatically
 * created on the fly and added to the root fixture, based on the
1045
 * slash-separated portions of @testpath.
1046 1047
 *
 * Since: 2.16
1048
 */
Tim Janik's avatar
Tim Janik committed
1049
void
1050 1051
g_test_add_func (const char *testpath,
                 GTestFunc   test_func)
Tim Janik's avatar
Tim Janik committed
1052 1053 1054 1055
{
  g_return_if_fail (testpath != NULL);
  g_return_if_fail (testpath[0] == '/');
  g_return_if_fail (test_func != NULL);
1056
  g_test_add_vtable (testpath, 0, NULL, NULL, (GTestFixtureFunc) test_func, NULL);
1057 1058
}

1059 1060 1061 1062 1063 1064
/**
 * GTestDataFunc:
 * @user_data: the data provided when registering the test
 *
 * The type used for test case functions that take an extra pointer
 * argument.
Matthias Clasen's avatar
Matthias Clasen committed
1065 1066 1067 1068
 *
 * Since: 2.28
 */

1069 1070
/**
 * g_test_add_data_func:
1071
 * @testpath:   Slash-separated test case path name for the test.
1072 1073 1074 1075 1076 1077
 * @test_data:  Test data argument for the test function.
 * @test_func:  The test function to invoke for this test.
 *
 * Create a new test case, similar to g_test_create_case(). However
 * the test is assumed to use no fixture, and test suites are automatically
 * created on the fly and added to the root fixture, based on the
1078
 * slash-separated portions of @testpath. The @test_data argument
1079
 * will be passed as first argument to @test_func.
1080 1081
 *
 * Since: 2.16
1082 1083 1084 1085
 */
void
g_test_add_data_func (const char     *testpath,
                      gconstpointer   test_data,
1086
                      GTestDataFunc   test_func)
1087 1088 1089 1090
{
  g_return_if_fail (testpath != NULL);
  g_return_if_fail (testpath[0] == '/');
  g_return_if_fail (test_func != NULL);
1091
  g_test_add_vtable (testpath, 0, test_data, NULL, (GTestFixtureFunc) test_func, NULL);
Tim Janik's avatar
Tim Janik committed
1092 1093
}

1094 1095 1096 1097 1098 1099 1100
/**
 * g_test_create_suite:
 * @suite_name: a name for the suite
 *
 * Create a new test suite with the name @suite_name.
 *
 * Returns: A newly allocated #GTestSuite instance.
1101 1102
 *
 * Since: 2.16
1103
 */
Tim Janik's avatar
Tim Janik committed
1104 1105 1106
GTestSuite*
g_test_create_suite (const char *suite_name)
{
1107
  GTestSuite *ts;
Tim Janik's avatar