gitee.com/quant1x/num@v0.3.2/asm/src/munit.c (about)

     1  /* Copyright (c) 2013-2018 Evan Nemerson <evan@nemerson.com>
     2   *
     3   * Permission is hereby granted, free of charge, to any person
     4   * obtaining a copy of this software and associated documentation
     5   * files (the "Software"), to deal in the Software without
     6   * restriction, including without limitation the rights to use, copy,
     7   * modify, merge, publish, distribute, sublicense, and/or sell copies
     8   * of the Software, and to permit persons to whom the Software is
     9   * furnished to do so, subject to the following conditions:
    10   *
    11   * The above copyright notice and this permission notice shall be
    12   * included in all copies or substantial portions of the Software.
    13   *
    14   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    15   * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    16   * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
    17   * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
    18   * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
    19   * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
    20   * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    21   * SOFTWARE.
    22   */
    23  
    24  /*** Configuration ***/
    25  
    26  /* This is just where the output from the test goes.  It's really just
    27   * meant to let you choose stdout or stderr, but if anyone really want
    28   * to direct it to a file let me know, it would be fairly easy to
    29   * support. */
    30  #if !defined(MUNIT_OUTPUT_FILE)
    31  #  define MUNIT_OUTPUT_FILE stdout
    32  #endif
    33  
    34  /* This is a bit more useful; it tells µnit how to format the seconds in
    35   * timed tests.  If your tests run for longer you might want to reduce
    36   * it, and if your computer is really fast and your tests are tiny you
    37   * can increase it. */
    38  #if !defined(MUNIT_TEST_TIME_FORMAT)
    39  #  define MUNIT_TEST_TIME_FORMAT "0.8f"
    40  #endif
    41  
    42  /* If you have long test names you might want to consider bumping
    43   * this.  The result information takes 43 characters. */
    44  #if !defined(MUNIT_TEST_NAME_LEN)
    45  #  define MUNIT_TEST_NAME_LEN 37
    46  #endif
    47  
    48  /* If you don't like the timing information, you can disable it by
    49   * defining MUNIT_DISABLE_TIMING. */
    50  #if !defined(MUNIT_DISABLE_TIMING)
    51  #  define MUNIT_ENABLE_TIMING
    52  #endif
    53  
    54  /*** End configuration ***/
    55  
    56  #if defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE < 200809L)
    57  #  undef _POSIX_C_SOURCE
    58  #endif
    59  #if !defined(_POSIX_C_SOURCE)
    60  #  define _POSIX_C_SOURCE 200809L
    61  #endif
    62  
    63  /* Solaris freaks out if you try to use a POSIX or SUS standard without
    64   * the "right" C standard. */
    65  #if defined(_XOPEN_SOURCE)
    66  #  undef _XOPEN_SOURCE
    67  #endif
    68  
    69  #if defined(__STDC_VERSION__)
    70  #  if __STDC_VERSION__ >= 201112L
    71  #    define _XOPEN_SOURCE 700
    72  #  elif __STDC_VERSION__ >= 199901L
    73  #    define _XOPEN_SOURCE 600
    74  #  endif
    75  #endif
    76  
    77  /* Because, according to Microsoft, POSIX is deprecated.  You've got
    78   * to appreciate the chutzpah. */
    79  #if defined(_MSC_VER) && !defined(_CRT_NONSTDC_NO_DEPRECATE)
    80  #  define _CRT_NONSTDC_NO_DEPRECATE
    81  #endif
    82  
    83  #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
    84  #  include <stdbool.h>
    85  #elif defined(_WIN32)
    86  /* https://msdn.microsoft.com/en-us/library/tf4dy80a.aspx */
    87  #endif
    88  
    89  #include <limits.h>
    90  #include <time.h>
    91  #include <errno.h>
    92  #include <string.h>
    93  #include <stdlib.h>
    94  #include <stdio.h>
    95  #include <stdarg.h>
    96  #include <setjmp.h>
    97  
    98  #if !defined(MUNIT_NO_NL_LANGINFO) && !defined(_WIN32)
    99  #define MUNIT_NL_LANGINFO
   100  #include <locale.h>
   101  #include <langinfo.h>
   102  #include <strings.h>
   103  #endif
   104  
   105  #if !defined(_WIN32)
   106  #  include <unistd.h>
   107  #  include <sys/types.h>
   108  #  include <sys/wait.h>
   109  #else
   110  #  include <windows.h>
   111  #  include <io.h>
   112  #  include <fcntl.h>
   113  #  if !defined(STDERR_FILENO)
   114  #    define STDERR_FILENO _fileno(stderr)
   115  #  endif
   116  #endif
   117  
   118  #include "munit.h"
   119  
   120  #define MUNIT_STRINGIFY(x) #x
   121  #define MUNIT_XSTRINGIFY(x) MUNIT_STRINGIFY(x)
   122  
   123  #if defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__SUNPRO_CC) || defined(__IBMCPP__)
   124  #  define MUNIT_THREAD_LOCAL __thread
   125  #elif (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201102L)) || defined(_Thread_local)
   126  #  define MUNIT_THREAD_LOCAL _Thread_local
   127  #elif defined(_WIN32)
   128  #  define MUNIT_THREAD_LOCAL __declspec(thread)
   129  #endif
   130  
   131  /* MSVC 12.0 will emit a warning at /W4 for code like 'do { ... }
   132   * while (0)', or 'do { ... } while (1)'.  I'm pretty sure nobody
   133   * at Microsoft compiles with /W4. */
   134  #if defined(_MSC_VER) && (_MSC_VER <= 1800)
   135  #pragma warning(disable: 4127)
   136  #endif
   137  
   138  #if defined(_WIN32) || defined(__EMSCRIPTEN__)
   139  #  define MUNIT_NO_FORK
   140  #endif
   141  
   142  #if defined(__EMSCRIPTEN__)
   143  #  define MUNIT_NO_BUFFER
   144  #endif
   145  
   146  /*** Logging ***/
   147  
   148  static MunitLogLevel munit_log_level_visible = MUNIT_LOG_INFO;
   149  static MunitLogLevel munit_log_level_fatal = MUNIT_LOG_ERROR;
   150  
   151  #if defined(MUNIT_THREAD_LOCAL)
   152  static MUNIT_THREAD_LOCAL munit_bool munit_error_jmp_buf_valid = 0;
   153  static MUNIT_THREAD_LOCAL jmp_buf munit_error_jmp_buf;
   154  #endif
   155  
   156  /* At certain warning levels, mingw will trigger warnings about
   157   * suggesting the format attribute, which we've explicity *not* set
   158   * because it will then choke on our attempts to use the MS-specific
   159   * I64 modifier for size_t (which we have to use since MSVC doesn't
   160   * support the C99 z modifier). */
   161  
   162  #if defined(__MINGW32__) || defined(__MINGW64__)
   163  #  pragma GCC diagnostic push
   164  #  pragma GCC diagnostic ignored "-Wsuggest-attribute=format"
   165  #endif
   166  
   167  MUNIT_PRINTF(5,0)
   168  static void
   169  munit_logf_exv(MunitLogLevel level, FILE* fp, const char* filename, int line, const char* format, va_list ap) {
   170    if (level < munit_log_level_visible)
   171      return;
   172  
   173    switch (level) {
   174      case MUNIT_LOG_DEBUG:
   175        fputs("Debug", fp);
   176        break;
   177      case MUNIT_LOG_INFO:
   178        fputs("Info", fp);
   179        break;
   180      case MUNIT_LOG_WARNING:
   181        fputs("Warning", fp);
   182        break;
   183      case MUNIT_LOG_ERROR:
   184        fputs("Error", fp);
   185        break;
   186      default:
   187        munit_logf_ex(MUNIT_LOG_ERROR, filename, line, "Invalid log level (%d)", level);
   188        return;
   189    }
   190  
   191    fputs(": ", fp);
   192    if (filename != NULL)
   193      fprintf(fp, "%s:%d: ", filename, line);
   194    vfprintf(fp, format, ap);
   195    fputc('\n', fp);
   196  }
   197  
   198  MUNIT_PRINTF(3,4)
   199  static void
   200  munit_logf_internal(MunitLogLevel level, FILE* fp, const char* format, ...) {
   201    va_list ap;
   202  
   203    va_start(ap, format);
   204    munit_logf_exv(level, fp, NULL, 0, format, ap);
   205    va_end(ap);
   206  }
   207  
   208  static void
   209  munit_log_internal(MunitLogLevel level, FILE* fp, const char* message) {
   210    munit_logf_internal(level, fp, "%s", message);
   211  }
   212  
   213  void
   214  munit_logf_ex(MunitLogLevel level, const char* filename, int line, const char* format, ...) {
   215    va_list ap;
   216  
   217    va_start(ap, format);
   218    munit_logf_exv(level, stderr, filename, line, format, ap);
   219    va_end(ap);
   220  
   221    if (level >= munit_log_level_fatal) {
   222  #if defined(MUNIT_THREAD_LOCAL)
   223      if (munit_error_jmp_buf_valid)
   224        longjmp(munit_error_jmp_buf, 1);
   225  #endif
   226      abort();
   227    }
   228  }
   229  
   230  void
   231  munit_errorf_ex(const char* filename, int line, const char* format, ...) {
   232    va_list ap;
   233  
   234    va_start(ap, format);
   235    munit_logf_exv(MUNIT_LOG_ERROR, stderr, filename, line, format, ap);
   236    va_end(ap);
   237  
   238  #if defined(MUNIT_THREAD_LOCAL)
   239    if (munit_error_jmp_buf_valid)
   240      longjmp(munit_error_jmp_buf, 1);
   241  #endif
   242    abort();
   243  }
   244  
   245  #if defined(__MINGW32__) || defined(__MINGW64__)
   246  #pragma GCC diagnostic pop
   247  #endif
   248  
   249  #if !defined(MUNIT_STRERROR_LEN)
   250  #  define MUNIT_STRERROR_LEN 80
   251  #endif
   252  
   253  static void
   254  munit_log_errno(MunitLogLevel level, FILE* fp, const char* msg) {
   255  #if defined(MUNIT_NO_STRERROR_R) || (defined(__MINGW32__) && !defined(MINGW_HAS_SECURE_API))
   256    munit_logf_internal(level, fp, "%s: %s (%d)", msg, strerror(errno), errno);
   257  #else
   258    char munit_error_str[MUNIT_STRERROR_LEN];
   259    munit_error_str[0] = '\0';
   260  
   261  #if !defined(_WIN32)
   262    strerror_r(errno, munit_error_str, MUNIT_STRERROR_LEN);
   263  #else
   264    strerror_s(munit_error_str, MUNIT_STRERROR_LEN, errno);
   265  #endif
   266  
   267    munit_logf_internal(level, fp, "%s: %s (%d)", msg, munit_error_str, errno);
   268  #endif
   269  }
   270  
   271  /*** Memory allocation ***/
   272  
   273  void*
   274  munit_malloc_ex(const char* filename, int line, size_t size) {
   275    void* ptr;
   276  
   277    if (size == 0)
   278      return NULL;
   279  
   280    ptr = calloc(1, size);
   281    if (MUNIT_UNLIKELY(ptr == NULL)) {
   282      munit_logf_ex(MUNIT_LOG_ERROR, filename, line, "Failed to allocate %" MUNIT_SIZE_MODIFIER "u bytes.", size);
   283    }
   284  
   285    return ptr;
   286  }
   287  
   288  /*** Timer code ***/
   289  
   290  #if defined(MUNIT_ENABLE_TIMING)
   291  
   292  #define psnip_uint64_t munit_uint64_t
   293  #define psnip_uint32_t munit_uint32_t
   294  
   295  /* Code copied from portable-snippets
   296   * <https://github.com/nemequ/portable-snippets/>.  If you need to
   297   * change something, please do it there so we can keep the code in
   298   * sync. */
   299  
   300  /* Clocks (v1)
   301   * Portable Snippets - https://gitub.com/nemequ/portable-snippets
   302   * Created by Evan Nemerson <evan@nemerson.com>
   303   *
   304   *   To the extent possible under law, the authors have waived all
   305   *   copyright and related or neighboring rights to this code.  For
   306   *   details, see the Creative Commons Zero 1.0 Universal license at
   307   *   https://creativecommons.org/publicdomain/zero/1.0/
   308   */
   309  
   310  #if !defined(PSNIP_CLOCK_H)
   311  #define PSNIP_CLOCK_H
   312  
   313  #if !defined(psnip_uint64_t)
   314  #  include "../exact-int/exact-int.h"
   315  #endif
   316  
   317  #if !defined(PSNIP_CLOCK_STATIC_INLINE)
   318  #  if defined(__GNUC__)
   319  #    define PSNIP_CLOCK__COMPILER_ATTRIBUTES __attribute__((__unused__))
   320  #  else
   321  #    define PSNIP_CLOCK__COMPILER_ATTRIBUTES
   322  #  endif
   323  
   324  #  define PSNIP_CLOCK__FUNCTION PSNIP_CLOCK__COMPILER_ATTRIBUTES static
   325  #endif
   326  
   327  enum PsnipClockType {
   328    /* This clock provides the current time, in units since 1970-01-01
   329     * 00:00:00 UTC not including leap seconds.  In other words, UNIX
   330     * time.  Keep in mind that this clock doesn't account for leap
   331     * seconds, and can go backwards (think NTP adjustments). */
   332    PSNIP_CLOCK_TYPE_WALL = 1,
   333    /* The CPU time is a clock which increases only when the current
   334     * process is active (i.e., it doesn't increment while blocking on
   335     * I/O). */
   336    PSNIP_CLOCK_TYPE_CPU = 2,
   337    /* Monotonic time is always running (unlike CPU time), but it only
   338       ever moves forward unless you reboot the system.  Things like NTP
   339       adjustments have no effect on this clock. */
   340    PSNIP_CLOCK_TYPE_MONOTONIC = 3
   341  };
   342  
   343  struct PsnipClockTimespec {
   344    psnip_uint64_t seconds;
   345    psnip_uint64_t nanoseconds;
   346  };
   347  
   348  /* Methods we support: */
   349  
   350  #define PSNIP_CLOCK_METHOD_CLOCK_GETTIME                   1
   351  #define PSNIP_CLOCK_METHOD_TIME                            2
   352  #define PSNIP_CLOCK_METHOD_GETTIMEOFDAY                    3
   353  #define PSNIP_CLOCK_METHOD_QUERYPERFORMANCECOUNTER         4
   354  #define PSNIP_CLOCK_METHOD_MACH_ABSOLUTE_TIME              5
   355  #define PSNIP_CLOCK_METHOD_CLOCK                           6
   356  #define PSNIP_CLOCK_METHOD_GETPROCESSTIMES                 7
   357  #define PSNIP_CLOCK_METHOD_GETRUSAGE                       8
   358  #define PSNIP_CLOCK_METHOD_GETSYSTEMTIMEPRECISEASFILETIME  9
   359  #define PSNIP_CLOCK_METHOD_GETTICKCOUNT64                 10
   360  
   361  #include <assert.h>
   362  
   363  #if defined(HEDLEY_UNREACHABLE)
   364  #  define PSNIP_CLOCK_UNREACHABLE() HEDLEY_UNREACHABLE()
   365  #else
   366  #  define PSNIP_CLOCK_UNREACHABLE() assert(0)
   367  #endif
   368  
   369  /* Choose an implementation */
   370  
   371  /* #undef PSNIP_CLOCK_WALL_METHOD */
   372  /* #undef PSNIP_CLOCK_CPU_METHOD */
   373  /* #undef PSNIP_CLOCK_MONOTONIC_METHOD */
   374  
   375  /* We want to be able to detect the libc implementation, so we include
   376     <limits.h> (<features.h> isn't available everywhere). */
   377  
   378  #if defined(__unix__) || defined(__unix) || defined(__linux__)
   379  #  include <limits.h>
   380  #  include <unistd.h>
   381  #endif
   382  
   383  #if defined(_POSIX_TIMERS) && (_POSIX_TIMERS > 0)
   384  /* These are known to work without librt.  If you know of others
   385   * please let us know so we can add them. */
   386  #  if \
   387    (defined(__GLIBC__) && (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 17))) || \
   388    (defined(__FreeBSD__))
   389  #    define PSNIP_CLOCK_HAVE_CLOCK_GETTIME
   390  #  elif !defined(PSNIP_CLOCK_NO_LIBRT)
   391  #    define PSNIP_CLOCK_HAVE_CLOCK_GETTIME
   392  #  endif
   393  #endif
   394  
   395  #if defined(_WIN32)
   396  #  if !defined(PSNIP_CLOCK_CPU_METHOD)
   397  #    define PSNIP_CLOCK_CPU_METHOD PSNIP_CLOCK_METHOD_GETPROCESSTIMES
   398  #  endif
   399  #  if !defined(PSNIP_CLOCK_MONOTONIC_METHOD)
   400  #    define PSNIP_CLOCK_MONOTONIC_METHOD PSNIP_CLOCK_METHOD_QUERYPERFORMANCECOUNTER
   401  #  endif
   402  #endif
   403  
   404  #if defined(__MACH__) && !defined(__gnu_hurd__)
   405  #  if !defined(PSNIP_CLOCK_MONOTONIC_METHOD)
   406  #    define PSNIP_CLOCK_MONOTONIC_METHOD PSNIP_CLOCK_METHOD_MACH_ABSOLUTE_TIME
   407  #  endif
   408  #endif
   409  
   410  #if defined(PSNIP_CLOCK_HAVE_CLOCK_GETTIME)
   411  #  include <time.h>
   412  #  if !defined(PSNIP_CLOCK_WALL_METHOD)
   413  #    if defined(CLOCK_REALTIME_PRECISE)
   414  #      define PSNIP_CLOCK_WALL_METHOD PSNIP_CLOCK_METHOD_CLOCK_GETTIME
   415  #      define PSNIP_CLOCK_CLOCK_GETTIME_WALL CLOCK_REALTIME_PRECISE
   416  #    elif !defined(__sun)
   417  #      define PSNIP_CLOCK_WALL_METHOD PSNIP_CLOCK_METHOD_CLOCK_GETTIME
   418  #      define PSNIP_CLOCK_CLOCK_GETTIME_WALL CLOCK_REALTIME
   419  #    endif
   420  #  endif
   421  #  if !defined(PSNIP_CLOCK_CPU_METHOD)
   422  #    if defined(_POSIX_CPUTIME) || defined(CLOCK_PROCESS_CPUTIME_ID)
   423  #      define PSNIP_CLOCK_CPU_METHOD PSNIP_CLOCK_METHOD_CLOCK_GETTIME
   424  #      define PSNIP_CLOCK_CLOCK_GETTIME_CPU CLOCK_PROCESS_CPUTIME_ID
   425  #    elif defined(CLOCK_VIRTUAL)
   426  #      define PSNIP_CLOCK_CPU_METHOD PSNIP_CLOCK_METHOD_CLOCK_GETTIME
   427  #      define PSNIP_CLOCK_CLOCK_GETTIME_CPU CLOCK_VIRTUAL
   428  #    endif
   429  #  endif
   430  #  if !defined(PSNIP_CLOCK_MONOTONIC_METHOD)
   431  #    if defined(CLOCK_MONOTONIC_RAW)
   432  #      define PSNIP_CLOCK_MONOTONIC_METHOD PSNIP_CLOCK_METHOD_CLOCK_GETTIME
   433  #      define PSNIP_CLOCK_CLOCK_GETTIME_MONOTONIC CLOCK_MONOTONIC
   434  #    elif defined(CLOCK_MONOTONIC_PRECISE)
   435  #      define PSNIP_CLOCK_MONOTONIC_METHOD PSNIP_CLOCK_METHOD_CLOCK_GETTIME
   436  #      define PSNIP_CLOCK_CLOCK_GETTIME_MONOTONIC CLOCK_MONOTONIC_PRECISE
   437  #    elif defined(_POSIX_MONOTONIC_CLOCK) || defined(CLOCK_MONOTONIC)
   438  #      define PSNIP_CLOCK_MONOTONIC_METHOD PSNIP_CLOCK_METHOD_CLOCK_GETTIME
   439  #      define PSNIP_CLOCK_CLOCK_GETTIME_MONOTONIC CLOCK_MONOTONIC
   440  #    endif
   441  #  endif
   442  #endif
   443  
   444  #if defined(_POSIX_VERSION) && (_POSIX_VERSION >= 200112L)
   445  #  if !defined(PSNIP_CLOCK_WALL_METHOD)
   446  #    define PSNIP_CLOCK_WALL_METHOD PSNIP_CLOCK_METHOD_GETTIMEOFDAY
   447  #  endif
   448  #endif
   449  
   450  #if !defined(PSNIP_CLOCK_WALL_METHOD)
   451  #  define PSNIP_CLOCK_WALL_METHOD PSNIP_CLOCK_METHOD_TIME
   452  #endif
   453  
   454  #if !defined(PSNIP_CLOCK_CPU_METHOD)
   455  #  define PSNIP_CLOCK_CPU_METHOD PSNIP_CLOCK_METHOD_CLOCK
   456  #endif
   457  
   458  /* Primarily here for testing. */
   459  #if !defined(PSNIP_CLOCK_MONOTONIC_METHOD) && defined(PSNIP_CLOCK_REQUIRE_MONOTONIC)
   460  #  error No monotonic clock found.
   461  #endif
   462  
   463  /* Implementations */
   464  
   465  #if \
   466    (defined(PSNIP_CLOCK_CPU_METHOD)       && (PSNIP_CLOCK_CPU_METHOD       == PSNIP_CLOCK_METHOD_CLOCK_GETTIME)) || \
   467    (defined(PSNIP_CLOCK_WALL_METHOD)      && (PSNIP_CLOCK_WALL_METHOD      == PSNIP_CLOCK_METHOD_CLOCK_GETTIME)) || \
   468    (defined(PSNIP_CLOCK_MONOTONIC_METHOD) && (PSNIP_CLOCK_MONOTONIC_METHOD == PSNIP_CLOCK_METHOD_CLOCK_GETTIME)) || \
   469    (defined(PSNIP_CLOCK_CPU_METHOD)       && (PSNIP_CLOCK_CPU_METHOD       == PSNIP_CLOCK_METHOD_CLOCK)) || \
   470    (defined(PSNIP_CLOCK_WALL_METHOD)      && (PSNIP_CLOCK_WALL_METHOD      == PSNIP_CLOCK_METHOD_CLOCK)) || \
   471    (defined(PSNIP_CLOCK_MONOTONIC_METHOD) && (PSNIP_CLOCK_MONOTONIC_METHOD == PSNIP_CLOCK_METHOD_CLOCK)) || \
   472    (defined(PSNIP_CLOCK_CPU_METHOD)       && (PSNIP_CLOCK_CPU_METHOD       == PSNIP_CLOCK_METHOD_TIME)) || \
   473    (defined(PSNIP_CLOCK_WALL_METHOD)      && (PSNIP_CLOCK_WALL_METHOD      == PSNIP_CLOCK_METHOD_TIME)) || \
   474    (defined(PSNIP_CLOCK_MONOTONIC_METHOD) && (PSNIP_CLOCK_MONOTONIC_METHOD == PSNIP_CLOCK_METHOD_TIME))
   475  #  include <time.h>
   476  #endif
   477  
   478  #if \
   479    (defined(PSNIP_CLOCK_CPU_METHOD)       && (PSNIP_CLOCK_CPU_METHOD       == PSNIP_CLOCK_METHOD_GETTIMEOFDAY)) || \
   480    (defined(PSNIP_CLOCK_WALL_METHOD)      && (PSNIP_CLOCK_WALL_METHOD      == PSNIP_CLOCK_METHOD_GETTIMEOFDAY)) || \
   481    (defined(PSNIP_CLOCK_MONOTONIC_METHOD) && (PSNIP_CLOCK_MONOTONIC_METHOD == PSNIP_CLOCK_METHOD_GETTIMEOFDAY))
   482  #  include <sys/time.h>
   483  #endif
   484  
   485  #if \
   486    (defined(PSNIP_CLOCK_CPU_METHOD)       && (PSNIP_CLOCK_CPU_METHOD       == PSNIP_CLOCK_METHOD_GETPROCESSTIMES)) || \
   487    (defined(PSNIP_CLOCK_WALL_METHOD)      && (PSNIP_CLOCK_WALL_METHOD      == PSNIP_CLOCK_METHOD_GETPROCESSTIMES)) || \
   488    (defined(PSNIP_CLOCK_MONOTONIC_METHOD) && (PSNIP_CLOCK_MONOTONIC_METHOD == PSNIP_CLOCK_METHOD_GETPROCESSTIMES)) || \
   489    (defined(PSNIP_CLOCK_CPU_METHOD)       && (PSNIP_CLOCK_CPU_METHOD       == PSNIP_CLOCK_METHOD_GETTICKCOUNT64)) || \
   490    (defined(PSNIP_CLOCK_WALL_METHOD)      && (PSNIP_CLOCK_WALL_METHOD      == PSNIP_CLOCK_METHOD_GETTICKCOUNT64)) || \
   491    (defined(PSNIP_CLOCK_MONOTONIC_METHOD) && (PSNIP_CLOCK_MONOTONIC_METHOD == PSNIP_CLOCK_METHOD_GETTICKCOUNT64))
   492  #  include <windows.h>
   493  #endif
   494  
   495  #if \
   496    (defined(PSNIP_CLOCK_CPU_METHOD)       && (PSNIP_CLOCK_CPU_METHOD       == PSNIP_CLOCK_METHOD_GETRUSAGE)) || \
   497    (defined(PSNIP_CLOCK_WALL_METHOD)      && (PSNIP_CLOCK_WALL_METHOD      == PSNIP_CLOCK_METHOD_GETRUSAGE)) || \
   498    (defined(PSNIP_CLOCK_MONOTONIC_METHOD) && (PSNIP_CLOCK_MONOTONIC_METHOD == PSNIP_CLOCK_METHOD_GETRUSAGE))
   499  #  include <sys/time.h>
   500  #  include <sys/resource.h>
   501  #endif
   502  
   503  #if \
   504    (defined(PSNIP_CLOCK_CPU_METHOD)       && (PSNIP_CLOCK_CPU_METHOD       == PSNIP_CLOCK_METHOD_MACH_ABSOLUTE_TIME)) || \
   505    (defined(PSNIP_CLOCK_WALL_METHOD)      && (PSNIP_CLOCK_WALL_METHOD      == PSNIP_CLOCK_METHOD_MACH_ABSOLUTE_TIME)) || \
   506    (defined(PSNIP_CLOCK_MONOTONIC_METHOD) && (PSNIP_CLOCK_MONOTONIC_METHOD == PSNIP_CLOCK_METHOD_MACH_ABSOLUTE_TIME))
   507  #  include <CoreServices/CoreServices.h>
   508  #  include <mach/mach.h>
   509  #  include <mach/mach_time.h>
   510  #endif
   511  
   512  /*** Implementations ***/
   513  
   514  #define PSNIP_CLOCK_NSEC_PER_SEC ((psnip_uint32_t) (1000000000ULL))
   515  
   516  #if \
   517    (defined(PSNIP_CLOCK_CPU_METHOD)       && (PSNIP_CLOCK_CPU_METHOD       == PSNIP_CLOCK_METHOD_CLOCK_GETTIME)) || \
   518    (defined(PSNIP_CLOCK_WALL_METHOD)      && (PSNIP_CLOCK_WALL_METHOD      == PSNIP_CLOCK_METHOD_CLOCK_GETTIME)) || \
   519    (defined(PSNIP_CLOCK_MONOTONIC_METHOD) && (PSNIP_CLOCK_MONOTONIC_METHOD == PSNIP_CLOCK_METHOD_CLOCK_GETTIME))
   520  PSNIP_CLOCK__FUNCTION psnip_uint32_t
   521  psnip_clock__clock_getres (clockid_t clk_id) {
   522    struct timespec res;
   523    int r;
   524  
   525    r = clock_getres(clk_id, &res);
   526    if (r != 0)
   527      return 0;
   528  
   529    return (psnip_uint32_t) (PSNIP_CLOCK_NSEC_PER_SEC / res.tv_nsec);
   530  }
   531  
   532  PSNIP_CLOCK__FUNCTION int
   533  psnip_clock__clock_gettime (clockid_t clk_id, struct PsnipClockTimespec* res) {
   534    struct timespec ts;
   535  
   536    if (clock_gettime(clk_id, &ts) != 0)
   537      return -10;
   538  
   539    res->seconds = (psnip_uint64_t) (ts.tv_sec);
   540    res->nanoseconds = (psnip_uint64_t) (ts.tv_nsec);
   541  
   542    return 0;
   543  }
   544  #endif
   545  
   546  PSNIP_CLOCK__FUNCTION psnip_uint32_t
   547  psnip_clock_wall_get_precision (void) {
   548  #if !defined(PSNIP_CLOCK_WALL_METHOD)
   549    return 0;
   550  #elif defined(PSNIP_CLOCK_WALL_METHOD) && PSNIP_CLOCK_WALL_METHOD == PSNIP_CLOCK_METHOD_CLOCK_GETTIME
   551    return psnip_clock__clock_getres(PSNIP_CLOCK_CLOCK_GETTIME_WALL);
   552  #elif defined(PSNIP_CLOCK_WALL_METHOD) && PSNIP_CLOCK_WALL_METHOD == PSNIP_CLOCK_METHOD_GETTIMEOFDAY
   553    return 1000000;
   554  #elif defined(PSNIP_CLOCK_WALL_METHOD) && PSNIP_CLOCK_WALL_METHOD == PSNIP_CLOCK_METHOD_TIME
   555    return 1;
   556  #else
   557    return 0;
   558  #endif
   559  }
   560  
   561  PSNIP_CLOCK__FUNCTION int
   562  psnip_clock_wall_get_time (struct PsnipClockTimespec* res) {
   563    (void) res;
   564  
   565  #if !defined(PSNIP_CLOCK_WALL_METHOD)
   566    return -2;
   567  #elif defined(PSNIP_CLOCK_WALL_METHOD) && PSNIP_CLOCK_WALL_METHOD == PSNIP_CLOCK_METHOD_CLOCK_GETTIME
   568    return psnip_clock__clock_gettime(PSNIP_CLOCK_CLOCK_GETTIME_WALL, res);
   569  #elif defined(PSNIP_CLOCK_WALL_METHOD) && PSNIP_CLOCK_WALL_METHOD == PSNIP_CLOCK_METHOD_TIME
   570    res->seconds = time(NULL);
   571    res->nanoseconds = 0;
   572  #elif defined(PSNIP_CLOCK_WALL_METHOD) && PSNIP_CLOCK_WALL_METHOD == PSNIP_CLOCK_METHOD_GETTIMEOFDAY
   573    struct timeval tv;
   574  
   575    if (gettimeofday(&tv, NULL) != 0)
   576      return -6;
   577  
   578    res->seconds = tv.tv_sec;
   579    res->nanoseconds = tv.tv_usec * 1000;
   580  #else
   581    return -2;
   582  #endif
   583  
   584    return 0;
   585  }
   586  
   587  PSNIP_CLOCK__FUNCTION psnip_uint32_t
   588  psnip_clock_cpu_get_precision (void) {
   589  #if !defined(PSNIP_CLOCK_CPU_METHOD)
   590    return 0;
   591  #elif defined(PSNIP_CLOCK_CPU_METHOD) && PSNIP_CLOCK_CPU_METHOD == PSNIP_CLOCK_METHOD_CLOCK_GETTIME
   592    return psnip_clock__clock_getres(PSNIP_CLOCK_CLOCK_GETTIME_CPU);
   593  #elif defined(PSNIP_CLOCK_CPU_METHOD) && PSNIP_CLOCK_CPU_METHOD == PSNIP_CLOCK_METHOD_CLOCK
   594    return CLOCKS_PER_SEC;
   595  #elif defined(PSNIP_CLOCK_CPU_METHOD) && PSNIP_CLOCK_CPU_METHOD == PSNIP_CLOCK_METHOD_GETPROCESSTIMES
   596    return PSNIP_CLOCK_NSEC_PER_SEC / 100;
   597  #else
   598    return 0;
   599  #endif
   600  }
   601  
   602  PSNIP_CLOCK__FUNCTION int
   603  psnip_clock_cpu_get_time (struct PsnipClockTimespec* res) {
   604  #if !defined(PSNIP_CLOCK_CPU_METHOD)
   605    (void) res;
   606    return -2;
   607  #elif defined(PSNIP_CLOCK_CPU_METHOD) && PSNIP_CLOCK_CPU_METHOD == PSNIP_CLOCK_METHOD_CLOCK_GETTIME
   608    return psnip_clock__clock_gettime(PSNIP_CLOCK_CLOCK_GETTIME_CPU, res);
   609  #elif defined(PSNIP_CLOCK_CPU_METHOD) && PSNIP_CLOCK_CPU_METHOD == PSNIP_CLOCK_METHOD_CLOCK
   610    clock_t t = clock();
   611    if (t == ((clock_t) -1))
   612      return -5;
   613    res->seconds = t / CLOCKS_PER_SEC;
   614    res->nanoseconds = (t % CLOCKS_PER_SEC) * (PSNIP_CLOCK_NSEC_PER_SEC / CLOCKS_PER_SEC);
   615  #elif defined(PSNIP_CLOCK_CPU_METHOD) && PSNIP_CLOCK_CPU_METHOD == PSNIP_CLOCK_METHOD_GETPROCESSTIMES
   616    FILETIME CreationTime, ExitTime, KernelTime, UserTime;
   617    LARGE_INTEGER date, adjust;
   618  
   619    if (!GetProcessTimes(GetCurrentProcess(), &CreationTime, &ExitTime, &KernelTime, &UserTime))
   620      return -7;
   621  
   622    /* http://www.frenk.com/2009/12/convert-filetime-to-unix-timestamp/ */
   623    date.HighPart = UserTime.dwHighDateTime;
   624    date.LowPart = UserTime.dwLowDateTime;
   625    adjust.QuadPart = 11644473600000 * 10000;
   626    date.QuadPart -= adjust.QuadPart;
   627  
   628    res->seconds = date.QuadPart / 10000000;
   629    res->nanoseconds = (date.QuadPart % 10000000) * (PSNIP_CLOCK_NSEC_PER_SEC / 100);
   630  #elif PSNIP_CLOCK_CPU_METHOD == PSNIP_CLOCK_METHOD_GETRUSAGE
   631    struct rusage usage;
   632    if (getrusage(RUSAGE_SELF, &usage) != 0)
   633      return -8;
   634  
   635    res->seconds = usage.ru_utime.tv_sec;
   636    res->nanoseconds = tv.tv_usec * 1000;
   637  #else
   638    (void) res;
   639    return -2;
   640  #endif
   641  
   642    return 0;
   643  }
   644  
   645  PSNIP_CLOCK__FUNCTION psnip_uint32_t
   646  psnip_clock_monotonic_get_precision (void) {
   647  #if !defined(PSNIP_CLOCK_MONOTONIC_METHOD)
   648    return 0;
   649  #elif defined(PSNIP_CLOCK_MONOTONIC_METHOD) && PSNIP_CLOCK_MONOTONIC_METHOD == PSNIP_CLOCK_METHOD_CLOCK_GETTIME
   650    return psnip_clock__clock_getres(PSNIP_CLOCK_CLOCK_GETTIME_MONOTONIC);
   651  #elif defined(PSNIP_CLOCK_MONOTONIC_METHOD) && PSNIP_CLOCK_MONOTONIC_METHOD == PSNIP_CLOCK_METHOD_MACH_ABSOLUTE_TIME
   652    static mach_timebase_info_data_t tbi = { 0, };
   653    if (tbi.denom == 0)
   654      mach_timebase_info(&tbi);
   655    return (psnip_uint32_t) (tbi.numer / tbi.denom);
   656  #elif defined(PSNIP_CLOCK_MONOTONIC_METHOD) && PSNIP_CLOCK_MONOTONIC_METHOD == PSNIP_CLOCK_METHOD_GETTICKCOUNT64
   657    return 1000;
   658  #elif defined(PSNIP_CLOCK_MONOTONIC_METHOD) && PSNIP_CLOCK_MONOTONIC_METHOD == PSNIP_CLOCK_METHOD_QUERYPERFORMANCECOUNTER
   659    LARGE_INTEGER Frequency;
   660    QueryPerformanceFrequency(&Frequency);
   661    return (psnip_uint32_t) ((Frequency.QuadPart > PSNIP_CLOCK_NSEC_PER_SEC) ? PSNIP_CLOCK_NSEC_PER_SEC : Frequency.QuadPart);
   662  #else
   663    return 0;
   664  #endif
   665  }
   666  
   667  PSNIP_CLOCK__FUNCTION int
   668  psnip_clock_monotonic_get_time (struct PsnipClockTimespec* res) {
   669  #if !defined(PSNIP_CLOCK_MONOTONIC_METHOD)
   670    (void) res;
   671    return -2;
   672  #elif defined(PSNIP_CLOCK_MONOTONIC_METHOD) && PSNIP_CLOCK_MONOTONIC_METHOD == PSNIP_CLOCK_METHOD_CLOCK_GETTIME
   673    return psnip_clock__clock_gettime(PSNIP_CLOCK_CLOCK_GETTIME_MONOTONIC, res);
   674  #elif defined(PSNIP_CLOCK_MONOTONIC_METHOD) && PSNIP_CLOCK_MONOTONIC_METHOD == PSNIP_CLOCK_METHOD_MACH_ABSOLUTE_TIME
   675    psnip_uint64_t nsec = mach_absolute_time();
   676    static mach_timebase_info_data_t tbi = { 0, };
   677    if (tbi.denom == 0)
   678      mach_timebase_info(&tbi);
   679    nsec *= ((psnip_uint64_t) tbi.numer) / ((psnip_uint64_t) tbi.denom);
   680    res->seconds = nsec / PSNIP_CLOCK_NSEC_PER_SEC;
   681    res->nanoseconds = nsec % PSNIP_CLOCK_NSEC_PER_SEC;
   682  #elif defined(PSNIP_CLOCK_MONOTONIC_METHOD) && PSNIP_CLOCK_MONOTONIC_METHOD == PSNIP_CLOCK_METHOD_QUERYPERFORMANCECOUNTER
   683    LARGE_INTEGER t, f;
   684    if (QueryPerformanceCounter(&t) == 0)
   685      return -12;
   686  
   687    QueryPerformanceFrequency(&f);
   688    res->seconds = t.QuadPart / f.QuadPart;
   689    res->nanoseconds = t.QuadPart % f.QuadPart;
   690    if (f.QuadPart > PSNIP_CLOCK_NSEC_PER_SEC)
   691      res->nanoseconds /= f.QuadPart / PSNIP_CLOCK_NSEC_PER_SEC;
   692    else
   693      res->nanoseconds *= PSNIP_CLOCK_NSEC_PER_SEC / f.QuadPart;
   694  #elif defined(PSNIP_CLOCK_MONOTONIC_METHOD) && PSNIP_CLOCK_MONOTONIC_METHOD == PSNIP_CLOCK_METHOD_GETTICKCOUNT64
   695    const ULONGLONG msec = GetTickCount64();
   696    res->seconds = msec / 1000;
   697    res->nanoseconds = sec % 1000;
   698  #else
   699    return -2;
   700  #endif
   701  
   702    return 0;
   703  }
   704  
   705  /* Returns the number of ticks per second for the specified clock.
   706   * For example, a clock with millisecond precision would return 1000,
   707   * and a clock with 1 second (such as the time() function) would
   708   * return 1.
   709   *
   710   * If the requested clock isn't available, it will return 0.
   711   * Hopefully this will be rare, but if it happens to you please let us
   712   * know so we can work on finding a way to support your system.
   713   *
   714   * Note that different clocks on the same system often have a
   715   * different precisions.
   716   */
   717  PSNIP_CLOCK__FUNCTION psnip_uint32_t
   718  psnip_clock_get_precision (enum PsnipClockType clock_type) {
   719    switch (clock_type) {
   720      case PSNIP_CLOCK_TYPE_MONOTONIC:
   721        return psnip_clock_monotonic_get_precision ();
   722      case PSNIP_CLOCK_TYPE_CPU:
   723        return psnip_clock_cpu_get_precision ();
   724      case PSNIP_CLOCK_TYPE_WALL:
   725        return psnip_clock_wall_get_precision ();
   726    }
   727  
   728    PSNIP_CLOCK_UNREACHABLE();
   729    return 0;
   730  }
   731  
   732  /* Set the provided timespec to the requested time.  Returns 0 on
   733   * success, or a negative value on failure. */
   734  PSNIP_CLOCK__FUNCTION int
   735  psnip_clock_get_time (enum PsnipClockType clock_type, struct PsnipClockTimespec* res) {
   736    assert(res != NULL);
   737  
   738    switch (clock_type) {
   739      case PSNIP_CLOCK_TYPE_MONOTONIC:
   740        return psnip_clock_monotonic_get_time (res);
   741      case PSNIP_CLOCK_TYPE_CPU:
   742        return psnip_clock_cpu_get_time (res);
   743      case PSNIP_CLOCK_TYPE_WALL:
   744        return psnip_clock_wall_get_time (res);
   745    }
   746  
   747    return -1;
   748  }
   749  
   750  #endif /* !defined(PSNIP_CLOCK_H) */
   751  
   752  static psnip_uint64_t
   753  munit_clock_get_elapsed(struct PsnipClockTimespec* start, struct PsnipClockTimespec* end) {
   754    psnip_uint64_t r = (end->seconds - start->seconds) * PSNIP_CLOCK_NSEC_PER_SEC;
   755    if (end->nanoseconds < start->nanoseconds) {
   756      r -= (start->nanoseconds - end->nanoseconds);
   757    } else {
   758      r += (end->nanoseconds - start->nanoseconds);
   759    }
   760    return r;
   761  }
   762  
   763  #else
   764  #  include <time.h>
   765  #endif /* defined(MUNIT_ENABLE_TIMING) */
   766  
   767  /*** PRNG stuff ***/
   768  
   769  /* This is (unless I screwed up, which is entirely possible) the
   770   * version of PCG with 32-bit state.  It was chosen because it has a
   771   * small enough state that we should reliably be able to use CAS
   772   * instead of requiring a lock for thread-safety.
   773   *
   774   * If I did screw up, I probably will not bother changing it unless
   775   * there is a significant bias.  It's really not important this be
   776   * particularly strong, as long as it is fairly random it's much more
   777   * important that it be reproducible, so bug reports have a better
   778   * chance of being reproducible. */
   779  
   780  #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && !defined(__STDC_NO_ATOMICS__) && !defined(__EMSCRIPTEN__) && (!defined(__GNUC_MINOR__) || (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ > 8))
   781  #  define HAVE_STDATOMIC
   782  #elif defined(__clang__)
   783  #  if __has_extension(c_atomic)
   784  #    define HAVE_CLANG_ATOMICS
   785  #  endif
   786  #endif
   787  
   788  /* Workaround for http://llvm.org/bugs/show_bug.cgi?id=26911 */
   789  #if defined(__clang__) && defined(_WIN32)
   790  #  undef HAVE_STDATOMIC
   791  #  if defined(__c2__)
   792  #    undef HAVE_CLANG_ATOMICS
   793  #  endif
   794  #endif
   795  
   796  #if defined(_OPENMP)
   797  #  define ATOMIC_UINT32_T uint32_t
   798  #  define ATOMIC_UINT32_INIT(x) (x)
   799  #elif defined(HAVE_STDATOMIC)
   800  #  include <stdatomic.h>
   801  #  define ATOMIC_UINT32_T _Atomic uint32_t
   802  #  define ATOMIC_UINT32_INIT(x) ATOMIC_VAR_INIT(x)
   803  #elif defined(HAVE_CLANG_ATOMICS)
   804  #  define ATOMIC_UINT32_T _Atomic uint32_t
   805  #  define ATOMIC_UINT32_INIT(x) (x)
   806  #elif defined(_WIN32)
   807  #  define ATOMIC_UINT32_T volatile LONG
   808  #  define ATOMIC_UINT32_INIT(x) (x)
   809  #else
   810  #  define ATOMIC_UINT32_T volatile uint32_t
   811  #  define ATOMIC_UINT32_INIT(x) (x)
   812  #endif
   813  
   814  static ATOMIC_UINT32_T munit_rand_state = ATOMIC_UINT32_INIT(42);
   815  
   816  #if defined(_OPENMP)
   817  static inline void
   818  munit_atomic_store(ATOMIC_UINT32_T* dest, ATOMIC_UINT32_T value) {
   819  #pragma omp critical (munit_atomics)
   820    *dest = value;
   821  }
   822  
   823  static inline uint32_t
   824  munit_atomic_load(ATOMIC_UINT32_T* src) {
   825    int ret;
   826  #pragma omp critical (munit_atomics)
   827    ret = *src;
   828    return ret;
   829  }
   830  
   831  static inline uint32_t
   832  munit_atomic_cas(ATOMIC_UINT32_T* dest, ATOMIC_UINT32_T* expected, ATOMIC_UINT32_T desired) {
   833    munit_bool ret;
   834  
   835  #pragma omp critical (munit_atomics)
   836    {
   837      if (*dest == *expected) {
   838        *dest = desired;
   839        ret = 1;
   840      } else {
   841        ret = 0;
   842      }
   843    }
   844  
   845    return ret;
   846  }
   847  #elif defined(HAVE_STDATOMIC)
   848  #  define munit_atomic_store(dest, value)         atomic_store(dest, value)
   849  #  define munit_atomic_load(src)                  atomic_load(src)
   850  #  define munit_atomic_cas(dest, expected, value) atomic_compare_exchange_weak(dest, expected, value)
   851  #elif defined(HAVE_CLANG_ATOMICS)
   852  #  define munit_atomic_store(dest, value)         __c11_atomic_store(dest, value, __ATOMIC_SEQ_CST)
   853  #  define munit_atomic_load(src)                  __c11_atomic_load(src, __ATOMIC_SEQ_CST)
   854  #  define munit_atomic_cas(dest, expected, value) __c11_atomic_compare_exchange_weak(dest, expected, value, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)
   855  #elif defined(__GNUC__) && (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)
   856  #  define munit_atomic_store(dest, value)         __atomic_store_n(dest, value, __ATOMIC_SEQ_CST)
   857  #  define munit_atomic_load(src)                  __atomic_load_n(src, __ATOMIC_SEQ_CST)
   858  #  define munit_atomic_cas(dest, expected, value) __atomic_compare_exchange_n(dest, expected, value, 1, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)
   859  #elif defined(__GNUC__) && (__GNUC__ >= 4)
   860  #  define munit_atomic_store(dest,value)          do { *(dest) = (value); } while (0)
   861  #  define munit_atomic_load(src)                  (*(src))
   862  #  define munit_atomic_cas(dest, expected, value) __sync_bool_compare_and_swap(dest, *expected, value)
   863  #elif defined(_WIN32) /* Untested */
   864  #  define munit_atomic_store(dest,value)          do { *(dest) = (value); } while (0)
   865  #  define munit_atomic_load(src)                  (*(src))
   866  #  define munit_atomic_cas(dest, expected, value) InterlockedCompareExchange((dest), (value), *(expected))
   867  #else
   868  #  warning No atomic implementation, PRNG will not be thread-safe
   869  #  define munit_atomic_store(dest, value)         do { *(dest) = (value); } while (0)
   870  #  define munit_atomic_load(src)                  (*(src))
   871  static inline munit_bool
   872  munit_atomic_cas(ATOMIC_UINT32_T* dest, ATOMIC_UINT32_T* expected, ATOMIC_UINT32_T desired) {
   873    if (*dest == *expected) {
   874      *dest = desired;
   875      return 1;
   876    } else {
   877      return 0;
   878    }
   879  }
   880  #endif
   881  
   882  #define MUNIT_PRNG_MULTIPLIER (747796405U)
   883  #define MUNIT_PRNG_INCREMENT  (1729U)
   884  
   885  static munit_uint32_t
   886  munit_rand_next_state(munit_uint32_t state) {
   887    return state * MUNIT_PRNG_MULTIPLIER + MUNIT_PRNG_INCREMENT;
   888  }
   889  
   890  static munit_uint32_t
   891  munit_rand_from_state(munit_uint32_t state) {
   892    munit_uint32_t res = ((state >> ((state >> 28) + 4)) ^ state) * (277803737U);
   893    res ^= res >> 22;
   894    return res;
   895  }
   896  
   897  void
   898  munit_rand_seed(munit_uint32_t seed) {
   899    munit_uint32_t state = munit_rand_next_state(seed + MUNIT_PRNG_INCREMENT);
   900    munit_atomic_store(&munit_rand_state, state);
   901  }
   902  
   903  static munit_uint32_t
   904  munit_rand_generate_seed(void) {
   905    munit_uint32_t seed, state;
   906  #if defined(MUNIT_ENABLE_TIMING)
   907    struct PsnipClockTimespec wc = { 0, };
   908  
   909    psnip_clock_get_time(PSNIP_CLOCK_TYPE_WALL, &wc);
   910    seed = (munit_uint32_t) wc.nanoseconds;
   911  #else
   912    seed = (munit_uint32_t) time(NULL);
   913  #endif
   914  
   915    state = munit_rand_next_state(seed + MUNIT_PRNG_INCREMENT);
   916    return munit_rand_from_state(state);
   917  }
   918  
   919  static munit_uint32_t
   920  munit_rand_state_uint32(munit_uint32_t* state) {
   921    const munit_uint32_t old = *state;
   922    *state = munit_rand_next_state(old);
   923    return munit_rand_from_state(old);
   924  }
   925  
   926  munit_uint32_t
   927  munit_rand_uint32(void) {
   928    munit_uint32_t old, state;
   929  
   930    do {
   931      old = munit_atomic_load(&munit_rand_state);
   932      state = munit_rand_next_state(old);
   933    } while (!munit_atomic_cas(&munit_rand_state, &old, state));
   934  
   935    return munit_rand_from_state(old);
   936  }
   937  
   938  static void
   939  munit_rand_state_memory(munit_uint32_t* state, size_t size, munit_uint8_t data[MUNIT_ARRAY_PARAM(size)]) {
   940    size_t members_remaining = size / sizeof(munit_uint32_t);
   941    size_t bytes_remaining = size % sizeof(munit_uint32_t);
   942    munit_uint8_t* b = data;
   943    munit_uint32_t rv;
   944    while (members_remaining-- > 0) {
   945      rv = munit_rand_state_uint32(state);
   946      memcpy(b, &rv, sizeof(munit_uint32_t));
   947      b += sizeof(munit_uint32_t);
   948    }
   949    if (bytes_remaining != 0) {
   950      rv = munit_rand_state_uint32(state);
   951      memcpy(b, &rv, bytes_remaining);
   952    }
   953  }
   954  
   955  void
   956  munit_rand_memory(size_t size, munit_uint8_t data[MUNIT_ARRAY_PARAM(size)]) {
   957    munit_uint32_t old, state;
   958  
   959    do {
   960      state = old = munit_atomic_load(&munit_rand_state);
   961      munit_rand_state_memory(&state, size, data);
   962    } while (!munit_atomic_cas(&munit_rand_state, &old, state));
   963  }
   964  
   965  static munit_uint32_t
   966  munit_rand_state_at_most(munit_uint32_t* state, munit_uint32_t salt, munit_uint32_t max) {
   967    /* We want (UINT32_MAX + 1) % max, which in unsigned arithmetic is the same
   968     * as (UINT32_MAX + 1 - max) % max = -max % max. We compute -max using not
   969     * to avoid compiler warnings.
   970     */
   971    const munit_uint32_t min = (~max + 1U) % max;
   972    munit_uint32_t x;
   973  
   974    if (max == (~((munit_uint32_t) 0U)))
   975      return munit_rand_state_uint32(state) ^ salt;
   976  
   977    max++;
   978  
   979    do {
   980      x = munit_rand_state_uint32(state) ^ salt;
   981    } while (x < min);
   982  
   983    return x % max;
   984  }
   985  
   986  static munit_uint32_t
   987  munit_rand_at_most(munit_uint32_t salt, munit_uint32_t max) {
   988    munit_uint32_t old, state;
   989    munit_uint32_t retval;
   990  
   991    do {
   992      state = old = munit_atomic_load(&munit_rand_state);
   993      retval = munit_rand_state_at_most(&state, salt, max);
   994    } while (!munit_atomic_cas(&munit_rand_state, &old, state));
   995  
   996    return retval;
   997  }
   998  
   999  int
  1000  munit_rand_int_range(int min, int max) {
  1001    munit_uint64_t range = (munit_uint64_t) max - (munit_uint64_t) min;
  1002  
  1003    if (min > max)
  1004      return munit_rand_int_range(max, min);
  1005  
  1006    if (range > (~((munit_uint32_t) 0U)))
  1007      range = (~((munit_uint32_t) 0U));
  1008  
  1009    return min + munit_rand_at_most(0, (munit_uint32_t) range);
  1010  }
  1011  
  1012  double
  1013  munit_rand_double(void) {
  1014    munit_uint32_t old, state;
  1015    double retval = 0.0;
  1016  
  1017    do {
  1018      state = old = munit_atomic_load(&munit_rand_state);
  1019  
  1020      /* See http://mumble.net/~campbell/tmp/random_real.c for how to do
  1021       * this right.  Patches welcome if you feel that this is too
  1022       * biased. */
  1023      retval = munit_rand_state_uint32(&state) / ((~((munit_uint32_t) 0U)) + 1.0);
  1024    } while (!munit_atomic_cas(&munit_rand_state, &old, state));
  1025  
  1026    return retval;
  1027  }
  1028  
  1029  /*** Test suite handling ***/
  1030  
  1031  typedef struct {
  1032    unsigned int successful;
  1033    unsigned int skipped;
  1034    unsigned int failed;
  1035    unsigned int errored;
  1036  #if defined(MUNIT_ENABLE_TIMING)
  1037    munit_uint64_t cpu_clock;
  1038    munit_uint64_t wall_clock;
  1039  #endif
  1040  } MunitReport;
  1041  
  1042  typedef struct {
  1043    const char* prefix;
  1044    const MunitSuite* suite;
  1045    const char** tests;
  1046    munit_uint32_t seed;
  1047    unsigned int iterations;
  1048    MunitParameter* parameters;
  1049    munit_bool single_parameter_mode;
  1050    void* user_data;
  1051    MunitReport report;
  1052    munit_bool colorize;
  1053    munit_bool fork;
  1054    munit_bool show_stderr;
  1055    munit_bool fatal_failures;
  1056  } MunitTestRunner;
  1057  
  1058  const char*
  1059  munit_parameters_get(const MunitParameter params[], const char* key) {
  1060    const MunitParameter* param;
  1061  
  1062    for (param = params ; param != NULL && param->name != NULL ; param++)
  1063      if (strcmp(param->name, key) == 0)
  1064        return param->value;
  1065    return NULL;
  1066  }
  1067  
  1068  #if defined(MUNIT_ENABLE_TIMING)
  1069  static void
  1070  munit_print_time(FILE* fp, munit_uint64_t nanoseconds) {
  1071    fprintf(fp, "%" MUNIT_TEST_TIME_FORMAT, ((double) nanoseconds) / ((double) PSNIP_CLOCK_NSEC_PER_SEC));
  1072  }
  1073  #endif
  1074  
  1075  /* Add a parameter to an array of parameters. */
  1076  static MunitResult
  1077  munit_parameters_add(size_t* params_size, MunitParameter* params[MUNIT_ARRAY_PARAM(*params_size)], char* name, char* value) {
  1078    *params = realloc(*params, sizeof(MunitParameter) * (*params_size + 2));
  1079    if (*params == NULL)
  1080      return MUNIT_ERROR;
  1081  
  1082    (*params)[*params_size].name = name;
  1083    (*params)[*params_size].value = value;
  1084    (*params_size)++;
  1085    (*params)[*params_size].name = NULL;
  1086    (*params)[*params_size].value = NULL;
  1087  
  1088    return MUNIT_OK;
  1089  }
  1090  
  1091  /* Concatenate two strings, but just return one of the components
  1092   * unaltered if the other is NULL or "". */
  1093  static char*
  1094  munit_maybe_concat(size_t* len, char* prefix, char* suffix) {
  1095    char* res;
  1096    size_t res_l;
  1097    const size_t prefix_l = prefix != NULL ? strlen(prefix) : 0;
  1098    const size_t suffix_l = suffix != NULL ? strlen(suffix) : 0;
  1099    if (prefix_l == 0 && suffix_l == 0) {
  1100      res = NULL;
  1101      res_l = 0;
  1102    } else if (prefix_l == 0 && suffix_l != 0) {
  1103      res = suffix;
  1104      res_l = suffix_l;
  1105    } else if (prefix_l != 0 && suffix_l == 0) {
  1106      res = prefix;
  1107      res_l = prefix_l;
  1108    } else {
  1109      res_l = prefix_l + suffix_l;
  1110      res = malloc(res_l + 1);
  1111      memcpy(res, prefix, prefix_l);
  1112      memcpy(res + prefix_l, suffix, suffix_l);
  1113      res[res_l] = 0;
  1114    }
  1115  
  1116    if (len != NULL)
  1117      *len = res_l;
  1118  
  1119    return res;
  1120  }
  1121  
  1122  /* Possbily free a string returned by munit_maybe_concat. */
  1123  static void
  1124  munit_maybe_free_concat(char* s, const char* prefix, const char* suffix) {
  1125    if (prefix != s && suffix != s)
  1126      free(s);
  1127  }
  1128  
  1129  /* Cheap string hash function, just used to salt the PRNG. */
  1130  static munit_uint32_t
  1131  munit_str_hash(const char* name) {
  1132    const char *p;
  1133    munit_uint32_t h = 5381U;
  1134  
  1135    for (p = name; *p != '\0'; p++)
  1136      h = (h << 5) + h + *p;
  1137  
  1138    return h;
  1139  }
  1140  
  1141  static void
  1142  munit_splice(int from, int to) {
  1143    munit_uint8_t buf[1024];
  1144  #if !defined(_WIN32)
  1145    ssize_t len;
  1146    ssize_t bytes_written;
  1147    ssize_t write_res;
  1148  #else
  1149    int len;
  1150    int bytes_written;
  1151    int write_res;
  1152  #endif
  1153    do {
  1154      len = read(from, buf, sizeof(buf));
  1155      if (len > 0) {
  1156        bytes_written = 0;
  1157        do {
  1158          write_res = write(to, buf + bytes_written, len - bytes_written);
  1159          if (write_res < 0)
  1160            break;
  1161          bytes_written += write_res;
  1162        } while (bytes_written < len);
  1163      }
  1164      else
  1165        break;
  1166    } while (1);
  1167  }
  1168  
  1169  /* This is the part that should be handled in the child process */
  1170  static MunitResult
  1171  munit_test_runner_exec(MunitTestRunner* runner, const MunitTest* test, const MunitParameter params[], MunitReport* report) {
  1172    unsigned int iterations = runner->iterations;
  1173    MunitResult result = MUNIT_FAIL;
  1174  #if defined(MUNIT_ENABLE_TIMING)
  1175    struct PsnipClockTimespec wall_clock_begin = { 0, }, wall_clock_end = { 0, };
  1176    struct PsnipClockTimespec cpu_clock_begin = { 0, }, cpu_clock_end = { 0, };
  1177  #endif
  1178    unsigned int i = 0;
  1179  
  1180    if ((test->options & MUNIT_TEST_OPTION_SINGLE_ITERATION) == MUNIT_TEST_OPTION_SINGLE_ITERATION)
  1181      iterations = 1;
  1182    else if (iterations == 0)
  1183      iterations = runner->suite->iterations;
  1184  
  1185    munit_rand_seed(runner->seed);
  1186  
  1187    do {
  1188      void* data = (test->setup == NULL) ? runner->user_data : test->setup(params, runner->user_data);
  1189  
  1190  #if defined(MUNIT_ENABLE_TIMING)
  1191      psnip_clock_get_time(PSNIP_CLOCK_TYPE_WALL, &wall_clock_begin);
  1192      psnip_clock_get_time(PSNIP_CLOCK_TYPE_CPU, &cpu_clock_begin);
  1193  #endif
  1194  
  1195      result = test->test(params, data);
  1196  
  1197  #if defined(MUNIT_ENABLE_TIMING)
  1198      psnip_clock_get_time(PSNIP_CLOCK_TYPE_WALL, &wall_clock_end);
  1199      psnip_clock_get_time(PSNIP_CLOCK_TYPE_CPU, &cpu_clock_end);
  1200  #endif
  1201  
  1202      if (test->tear_down != NULL)
  1203        test->tear_down(data);
  1204  
  1205      if (MUNIT_LIKELY(result == MUNIT_OK)) {
  1206        report->successful++;
  1207  #if defined(MUNIT_ENABLE_TIMING)
  1208        report->wall_clock += munit_clock_get_elapsed(&wall_clock_begin, &wall_clock_end);
  1209        report->cpu_clock += munit_clock_get_elapsed(&cpu_clock_begin, &cpu_clock_end);
  1210  #endif
  1211      } else {
  1212        switch ((int) result) {
  1213          case MUNIT_SKIP:
  1214            report->skipped++;
  1215            break;
  1216          case MUNIT_FAIL:
  1217            report->failed++;
  1218            break;
  1219          case MUNIT_ERROR:
  1220            report->errored++;
  1221            break;
  1222          default:
  1223            break;
  1224        }
  1225        break;
  1226      }
  1227    } while (++i < iterations);
  1228  
  1229    return result;
  1230  }
  1231  
  1232  #if defined(MUNIT_EMOTICON)
  1233  #  define MUNIT_RESULT_STRING_OK    ":)"
  1234  #  define MUNIT_RESULT_STRING_SKIP  ":|"
  1235  #  define MUNIT_RESULT_STRING_FAIL  ":("
  1236  #  define MUNIT_RESULT_STRING_ERROR ":o"
  1237  #  define MUNIT_RESULT_STRING_TODO  ":/"
  1238  #else
  1239  #  define MUNIT_RESULT_STRING_OK    "OK   "
  1240  #  define MUNIT_RESULT_STRING_SKIP  "SKIP "
  1241  #  define MUNIT_RESULT_STRING_FAIL  "FAIL "
  1242  #  define MUNIT_RESULT_STRING_ERROR "ERROR"
  1243  #  define MUNIT_RESULT_STRING_TODO  "TODO "
  1244  #endif
  1245  
  1246  static void
  1247  munit_test_runner_print_color(const MunitTestRunner* runner, const char* string, char color) {
  1248    if (runner->colorize)
  1249      fprintf(MUNIT_OUTPUT_FILE, "\x1b[3%cm%s\x1b[39m", color, string);
  1250    else
  1251      fputs(string, MUNIT_OUTPUT_FILE);
  1252  }
  1253  
  1254  #if !defined(MUNIT_NO_BUFFER)
  1255  static int
  1256  munit_replace_stderr(FILE* stderr_buf) {
  1257    if (stderr_buf != NULL) {
  1258      const int orig_stderr = dup(STDERR_FILENO);
  1259  
  1260      int errfd = fileno(stderr_buf);
  1261      if (MUNIT_UNLIKELY(errfd == -1)) {
  1262        exit(EXIT_FAILURE);
  1263      }
  1264  
  1265      dup2(errfd, STDERR_FILENO);
  1266  
  1267      return orig_stderr;
  1268    }
  1269  
  1270    return -1;
  1271  }
  1272  
  1273  static void
  1274  munit_restore_stderr(int orig_stderr) {
  1275    if (orig_stderr != -1) {
  1276      dup2(orig_stderr, STDERR_FILENO);
  1277      close(orig_stderr);
  1278    }
  1279  }
  1280  #endif /* !defined(MUNIT_NO_BUFFER) */
  1281  
  1282  /* Run a test with the specified parameters. */
  1283  static void
  1284  munit_test_runner_run_test_with_params(MunitTestRunner* runner, const MunitTest* test, const MunitParameter params[]) {
  1285    MunitResult result = MUNIT_OK;
  1286    MunitReport report = {
  1287      0, 0, 0, 0,
  1288  #if defined(MUNIT_ENABLE_TIMING)
  1289      0, 0
  1290  #endif
  1291    };
  1292    unsigned int output_l;
  1293    munit_bool first;
  1294    const MunitParameter* param;
  1295    FILE* stderr_buf;
  1296  #if !defined(MUNIT_NO_FORK)
  1297    int pipefd[2];
  1298    pid_t fork_pid;
  1299    int orig_stderr;
  1300    ssize_t bytes_written = 0;
  1301    ssize_t write_res;
  1302    ssize_t bytes_read = 0;
  1303    ssize_t read_res;
  1304    int status = 0;
  1305    pid_t changed_pid;
  1306  #endif
  1307  
  1308    if (params != NULL) {
  1309      output_l = 2;
  1310      fputs("  ", MUNIT_OUTPUT_FILE);
  1311      first = 1;
  1312      for (param = params ; param != NULL && param->name != NULL ; param++) {
  1313        if (!first) {
  1314          fputs(", ", MUNIT_OUTPUT_FILE);
  1315          output_l += 2;
  1316        } else {
  1317          first = 0;
  1318        }
  1319  
  1320        output_l += fprintf(MUNIT_OUTPUT_FILE, "%s=%s", param->name, param->value);
  1321      }
  1322      while (output_l++ < MUNIT_TEST_NAME_LEN) {
  1323        fputc(' ', MUNIT_OUTPUT_FILE);
  1324      }
  1325    }
  1326  
  1327    fflush(MUNIT_OUTPUT_FILE);
  1328  
  1329    stderr_buf = NULL;
  1330  #if !defined(_WIN32) || defined(__MINGW32__)
  1331    stderr_buf = tmpfile();
  1332  #else
  1333    tmpfile_s(&stderr_buf);
  1334  #endif
  1335    if (stderr_buf == NULL) {
  1336      munit_log_errno(MUNIT_LOG_ERROR, stderr, "unable to create buffer for stderr");
  1337      result = MUNIT_ERROR;
  1338      goto print_result;
  1339    }
  1340  
  1341  #if !defined(MUNIT_NO_FORK)
  1342    if (runner->fork) {
  1343      pipefd[0] = -1;
  1344      pipefd[1] = -1;
  1345      if (pipe(pipefd) != 0) {
  1346        munit_log_errno(MUNIT_LOG_ERROR, stderr, "unable to create pipe");
  1347        result = MUNIT_ERROR;
  1348        goto print_result;
  1349      }
  1350  
  1351      fork_pid = fork();
  1352      if (fork_pid == 0) {
  1353        close(pipefd[0]);
  1354  
  1355        orig_stderr = munit_replace_stderr(stderr_buf);
  1356        munit_test_runner_exec(runner, test, params, &report);
  1357  
  1358        /* Note that we don't restore stderr.  This is so we can buffer
  1359         * things written to stderr later on (such as by
  1360         * asan/tsan/ubsan, valgrind, etc.) */
  1361        close(orig_stderr);
  1362  
  1363        do {
  1364          write_res = write(pipefd[1], ((munit_uint8_t*) (&report)) + bytes_written, sizeof(report) - bytes_written);
  1365          if (write_res < 0) {
  1366            if (stderr_buf != NULL) {
  1367              munit_log_errno(MUNIT_LOG_ERROR, stderr, "unable to write to pipe");
  1368            }
  1369            exit(EXIT_FAILURE);
  1370          }
  1371          bytes_written += write_res;
  1372        } while ((size_t) bytes_written < sizeof(report));
  1373  
  1374        if (stderr_buf != NULL)
  1375          fclose(stderr_buf);
  1376        close(pipefd[1]);
  1377  
  1378        exit(EXIT_SUCCESS);
  1379      } else if (fork_pid == -1) {
  1380        close(pipefd[0]);
  1381        close(pipefd[1]);
  1382        if (stderr_buf != NULL) {
  1383          munit_log_errno(MUNIT_LOG_ERROR, stderr, "unable to fork");
  1384        }
  1385        report.errored++;
  1386        result = MUNIT_ERROR;
  1387      } else {
  1388        close(pipefd[1]);
  1389        do {
  1390          read_res = read(pipefd[0], ((munit_uint8_t*) (&report)) + bytes_read, sizeof(report) - bytes_read);
  1391          if (read_res < 1)
  1392            break;
  1393          bytes_read += read_res;
  1394        } while (bytes_read < (ssize_t) sizeof(report));
  1395  
  1396        changed_pid = waitpid(fork_pid, &status, 0);
  1397  
  1398        if (MUNIT_LIKELY(changed_pid == fork_pid) && MUNIT_LIKELY(WIFEXITED(status))) {
  1399          if (bytes_read != sizeof(report)) {
  1400            munit_logf_internal(MUNIT_LOG_ERROR, stderr_buf, "child exited unexpectedly with status %d", WEXITSTATUS(status));
  1401            report.errored++;
  1402          } else if (WEXITSTATUS(status) != EXIT_SUCCESS) {
  1403            munit_logf_internal(MUNIT_LOG_ERROR, stderr_buf, "child exited with status %d", WEXITSTATUS(status));
  1404            report.errored++;
  1405          }
  1406        } else {
  1407          if (WIFSIGNALED(status)) {
  1408  #if defined(_XOPEN_VERSION) && (_XOPEN_VERSION >= 700)
  1409            munit_logf_internal(MUNIT_LOG_ERROR, stderr_buf, "child killed by signal %d (%s)", WTERMSIG(status), strsignal(WTERMSIG(status)));
  1410  #else
  1411            munit_logf_internal(MUNIT_LOG_ERROR, stderr_buf, "child killed by signal %d", WTERMSIG(status));
  1412  #endif
  1413          } else if (WIFSTOPPED(status)) {
  1414            munit_logf_internal(MUNIT_LOG_ERROR, stderr_buf, "child stopped by signal %d", WSTOPSIG(status));
  1415          }
  1416          report.errored++;
  1417        }
  1418  
  1419        close(pipefd[0]);
  1420        waitpid(fork_pid, NULL, 0);
  1421      }
  1422    } else
  1423  #endif
  1424    {
  1425  #if !defined(MUNIT_NO_BUFFER)
  1426      const volatile int orig_stderr = munit_replace_stderr(stderr_buf);
  1427  #endif
  1428  
  1429  #if defined(MUNIT_THREAD_LOCAL)
  1430      if (MUNIT_UNLIKELY(setjmp(munit_error_jmp_buf) != 0)) {
  1431        result = MUNIT_FAIL;
  1432        report.failed++;
  1433      } else {
  1434        munit_error_jmp_buf_valid = 1;
  1435        result = munit_test_runner_exec(runner, test, params, &report);
  1436      }
  1437  #else
  1438      result = munit_test_runner_exec(runner, test, params, &report);
  1439  #endif
  1440  
  1441  #if !defined(MUNIT_NO_BUFFER)
  1442      munit_restore_stderr(orig_stderr);
  1443  #endif
  1444  
  1445      /* Here just so that the label is used on Windows and we don't get
  1446       * a warning */
  1447      goto print_result;
  1448    }
  1449  
  1450   print_result:
  1451  
  1452    fputs("[ ", MUNIT_OUTPUT_FILE);
  1453    if ((test->options & MUNIT_TEST_OPTION_TODO) == MUNIT_TEST_OPTION_TODO) {
  1454      if (report.failed != 0 || report.errored != 0 || report.skipped != 0) {
  1455        munit_test_runner_print_color(runner, MUNIT_RESULT_STRING_TODO, '3');
  1456        result = MUNIT_OK;
  1457      } else {
  1458        munit_test_runner_print_color(runner, MUNIT_RESULT_STRING_ERROR, '1');
  1459        if (MUNIT_LIKELY(stderr_buf != NULL))
  1460          munit_log_internal(MUNIT_LOG_ERROR, stderr_buf, "Test marked TODO, but was successful.");
  1461        runner->report.failed++;
  1462        result = MUNIT_ERROR;
  1463      }
  1464    } else if (report.failed > 0) {
  1465      munit_test_runner_print_color(runner, MUNIT_RESULT_STRING_FAIL, '1');
  1466      runner->report.failed++;
  1467      result = MUNIT_FAIL;
  1468    } else if (report.errored > 0) {
  1469      munit_test_runner_print_color(runner, MUNIT_RESULT_STRING_ERROR, '1');
  1470      runner->report.errored++;
  1471      result = MUNIT_ERROR;
  1472    } else if (report.skipped > 0) {
  1473      munit_test_runner_print_color(runner, MUNIT_RESULT_STRING_SKIP, '3');
  1474      runner->report.skipped++;
  1475      result = MUNIT_SKIP;
  1476    } else if (report.successful > 1) {
  1477      munit_test_runner_print_color(runner, MUNIT_RESULT_STRING_OK, '2');
  1478  #if defined(MUNIT_ENABLE_TIMING)
  1479      fputs(" ] [ ", MUNIT_OUTPUT_FILE);
  1480      munit_print_time(MUNIT_OUTPUT_FILE, report.wall_clock / report.successful);
  1481      fputs(" / ", MUNIT_OUTPUT_FILE);
  1482      munit_print_time(MUNIT_OUTPUT_FILE, report.cpu_clock / report.successful);
  1483      fprintf(MUNIT_OUTPUT_FILE, " CPU ]\n  %-" MUNIT_XSTRINGIFY(MUNIT_TEST_NAME_LEN) "s Total: [ ", "");
  1484      munit_print_time(MUNIT_OUTPUT_FILE, report.wall_clock);
  1485      fputs(" / ", MUNIT_OUTPUT_FILE);
  1486      munit_print_time(MUNIT_OUTPUT_FILE, report.cpu_clock);
  1487      fputs(" CPU", MUNIT_OUTPUT_FILE);
  1488  #endif
  1489      runner->report.successful++;
  1490      result = MUNIT_OK;
  1491    } else if (report.successful > 0) {
  1492      munit_test_runner_print_color(runner, MUNIT_RESULT_STRING_OK, '2');
  1493  #if defined(MUNIT_ENABLE_TIMING)
  1494      fputs(" ] [ ", MUNIT_OUTPUT_FILE);
  1495      munit_print_time(MUNIT_OUTPUT_FILE, report.wall_clock);
  1496      fputs(" / ", MUNIT_OUTPUT_FILE);
  1497      munit_print_time(MUNIT_OUTPUT_FILE, report.cpu_clock);
  1498      fputs(" CPU", MUNIT_OUTPUT_FILE);
  1499  #endif
  1500      runner->report.successful++;
  1501      result = MUNIT_OK;
  1502    }
  1503    fputs(" ]\n", MUNIT_OUTPUT_FILE);
  1504  
  1505    if (stderr_buf != NULL) {
  1506      if (result == MUNIT_FAIL || result == MUNIT_ERROR || runner->show_stderr) {
  1507        fflush(MUNIT_OUTPUT_FILE);
  1508  
  1509        rewind(stderr_buf);
  1510        munit_splice(fileno(stderr_buf), STDERR_FILENO);
  1511  
  1512        fflush(stderr);
  1513      }
  1514  
  1515      fclose(stderr_buf);
  1516    }
  1517  }
  1518  
  1519  static void
  1520  munit_test_runner_run_test_wild(MunitTestRunner* runner,
  1521                                  const MunitTest* test,
  1522                                  const char* test_name,
  1523                                  MunitParameter* params,
  1524                                  MunitParameter* p) {
  1525    const MunitParameterEnum* pe;
  1526    char** values;
  1527    MunitParameter* next;
  1528  
  1529    for (pe = test->parameters ; pe != NULL && pe->name != NULL ; pe++) {
  1530      if (p->name == pe->name)
  1531        break;
  1532    }
  1533  
  1534    if (pe == NULL)
  1535      return;
  1536  
  1537    for (values = pe->values ; *values != NULL ; values++) {
  1538      next = p + 1;
  1539      p->value = *values;
  1540      if (next->name == NULL) {
  1541        munit_test_runner_run_test_with_params(runner, test, params);
  1542      } else {
  1543        munit_test_runner_run_test_wild(runner, test, test_name, params, next);
  1544      }
  1545      if (runner->fatal_failures && (runner->report.failed != 0 || runner->report.errored != 0))
  1546        break;
  1547    }
  1548  }
  1549  
  1550  /* Run a single test, with every combination of parameters
  1551   * requested. */
  1552  static void
  1553  munit_test_runner_run_test(MunitTestRunner* runner,
  1554                             const MunitTest* test,
  1555                             const char* prefix) {
  1556    char* test_name = munit_maybe_concat(NULL, (char*) prefix, (char*) test->name);
  1557    /* The array of parameters to pass to
  1558     * munit_test_runner_run_test_with_params */
  1559    MunitParameter* params = NULL;
  1560    size_t params_l = 0;
  1561    /* Wildcard parameters are parameters which have possible values
  1562     * specified in the test, but no specific value was passed to the
  1563     * CLI.  That means we want to run the test once for every
  1564     * possible combination of parameter values or, if --single was
  1565     * passed to the CLI, a single time with a random set of
  1566     * parameters. */
  1567    MunitParameter* wild_params = NULL;
  1568    size_t wild_params_l = 0;
  1569    const MunitParameterEnum* pe;
  1570    const MunitParameter* cli_p;
  1571    munit_bool filled;
  1572    unsigned int possible;
  1573    char** vals;
  1574    size_t first_wild;
  1575    const MunitParameter* wp;
  1576    int pidx;
  1577  
  1578    munit_rand_seed(runner->seed);
  1579  
  1580    fprintf(MUNIT_OUTPUT_FILE, "%-" MUNIT_XSTRINGIFY(MUNIT_TEST_NAME_LEN) "s", test_name);
  1581  
  1582    if (test->parameters == NULL) {
  1583      /* No parameters.  Simple, nice. */
  1584      munit_test_runner_run_test_with_params(runner, test, NULL);
  1585    } else {
  1586      fputc('\n', MUNIT_OUTPUT_FILE);
  1587  
  1588      for (pe = test->parameters ; pe != NULL && pe->name != NULL ; pe++) {
  1589        /* Did we received a value for this parameter from the CLI? */
  1590        filled = 0;
  1591        for (cli_p = runner->parameters ; cli_p != NULL && cli_p->name != NULL ; cli_p++) {
  1592          if (strcmp(cli_p->name, pe->name) == 0) {
  1593            if (MUNIT_UNLIKELY(munit_parameters_add(&params_l, &params, pe->name, cli_p->value) != MUNIT_OK))
  1594              goto cleanup;
  1595            filled = 1;
  1596            break;
  1597          }
  1598        }
  1599        if (filled)
  1600          continue;
  1601  
  1602        /* Nothing from CLI, is the enum NULL/empty?  We're not a
  1603         * fuzzer… */
  1604        if (pe->values == NULL || pe->values[0] == NULL)
  1605          continue;
  1606  
  1607        /* If --single was passed to the CLI, choose a value from the
  1608         * list of possibilities randomly. */
  1609        if (runner->single_parameter_mode) {
  1610          possible = 0;
  1611          for (vals = pe->values ; *vals != NULL ; vals++)
  1612            possible++;
  1613          /* We want the tests to be reproducible, even if you're only
  1614           * running a single test, but we don't want every test with
  1615           * the same number of parameters to choose the same parameter
  1616           * number, so use the test name as a primitive salt. */
  1617          pidx = munit_rand_at_most(munit_str_hash(test_name), possible - 1);
  1618          if (MUNIT_UNLIKELY(munit_parameters_add(&params_l, &params, pe->name, pe->values[pidx]) != MUNIT_OK))
  1619            goto cleanup;
  1620        } else {
  1621          /* We want to try every permutation.  Put in a placeholder
  1622           * entry, we'll iterate through them later. */
  1623          if (MUNIT_UNLIKELY(munit_parameters_add(&wild_params_l, &wild_params, pe->name, NULL) != MUNIT_OK))
  1624            goto cleanup;
  1625        }
  1626      }
  1627  
  1628      if (wild_params_l != 0) {
  1629        first_wild = params_l;
  1630        for (wp = wild_params ; wp != NULL && wp->name != NULL ; wp++) {
  1631          for (pe = test->parameters ; pe != NULL && pe->name != NULL && pe->values != NULL ; pe++) {
  1632            if (strcmp(wp->name, pe->name) == 0) {
  1633              if (MUNIT_UNLIKELY(munit_parameters_add(&params_l, &params, pe->name, pe->values[0]) != MUNIT_OK))
  1634                goto cleanup;
  1635            }
  1636          }
  1637        }
  1638  
  1639        munit_test_runner_run_test_wild(runner, test, test_name, params, params + first_wild);
  1640      } else {
  1641        munit_test_runner_run_test_with_params(runner, test, params);
  1642      }
  1643  
  1644    cleanup:
  1645      free(params);
  1646      free(wild_params);
  1647    }
  1648  
  1649    munit_maybe_free_concat(test_name, prefix, test->name);
  1650  }
  1651  
  1652  /* Recurse through the suite and run all the tests.  If a list of
  1653   * tests to run was provied on the command line, run only those
  1654   * tests.  */
  1655  static void
  1656  munit_test_runner_run_suite(MunitTestRunner* runner,
  1657                              const MunitSuite* suite,
  1658                              const char* prefix) {
  1659    size_t pre_l;
  1660    char* pre = munit_maybe_concat(&pre_l, (char*) prefix, (char*) suite->prefix);
  1661    const MunitTest* test;
  1662    const char** test_name;
  1663    const MunitSuite* child_suite;
  1664  
  1665    /* Run the tests. */
  1666    for (test = suite->tests ; test != NULL && test->test != NULL ; test++) {
  1667      if (runner->tests != NULL) { /* Specific tests were requested on the CLI */
  1668        for (test_name = runner->tests ; test_name != NULL && *test_name != NULL ; test_name++) {
  1669          if ((pre_l == 0 || strncmp(pre, *test_name, pre_l) == 0) &&
  1670              strncmp(test->name, *test_name + pre_l, strlen(*test_name + pre_l)) == 0) {
  1671            munit_test_runner_run_test(runner, test, pre);
  1672            if (runner->fatal_failures && (runner->report.failed != 0 || runner->report.errored != 0))
  1673              goto cleanup;
  1674          }
  1675        }
  1676      } else { /* Run all tests */
  1677        munit_test_runner_run_test(runner, test, pre);
  1678      }
  1679    }
  1680  
  1681    if (runner->fatal_failures && (runner->report.failed != 0 || runner->report.errored != 0))
  1682      goto cleanup;
  1683  
  1684    /* Run any child suites. */
  1685    for (child_suite = suite->suites ; child_suite != NULL && child_suite->prefix != NULL ; child_suite++) {
  1686      munit_test_runner_run_suite(runner, child_suite, pre);
  1687    }
  1688  
  1689   cleanup:
  1690  
  1691    munit_maybe_free_concat(pre, prefix, suite->prefix);
  1692  }
  1693  
  1694  static void
  1695  munit_test_runner_run(MunitTestRunner* runner) {
  1696    munit_test_runner_run_suite(runner, runner->suite, NULL);
  1697  }
  1698  
  1699  static void
  1700  munit_print_help(int argc, char* const argv[MUNIT_ARRAY_PARAM(argc + 1)], void* user_data, const MunitArgument arguments[]) {
  1701    const MunitArgument* arg;
  1702    (void) argc;
  1703  
  1704    printf("USAGE: %s [OPTIONS...] [TEST...]\n\n", argv[0]);
  1705    puts(" --seed SEED\n"
  1706         "           Value used to seed the PRNG.  Must be a 32-bit integer in decimal\n"
  1707         "           notation with no separators (commas, decimals, spaces, etc.), or\n"
  1708         "           hexadecimal prefixed by \"0x\".\n"
  1709         " --iterations N\n"
  1710         "           Run each test N times.  0 means the default number.\n"
  1711         " --param name value\n"
  1712         "           A parameter key/value pair which will be passed to any test with\n"
  1713         "           takes a parameter of that name.  If not provided, the test will be\n"
  1714         "           run once for each possible parameter value.\n"
  1715         " --list    Write a list of all available tests.\n"
  1716         " --list-params\n"
  1717         "           Write a list of all available tests and their possible parameters.\n"
  1718         " --single  Run each parameterized test in a single configuration instead of\n"
  1719         "           every possible combination\n"
  1720         " --log-visible debug|info|warning|error\n"
  1721         " --log-fatal debug|info|warning|error\n"
  1722         "           Set the level at which messages of different severities are visible,\n"
  1723         "           or cause the test to terminate.\n"
  1724  #if !defined(MUNIT_NO_FORK)
  1725         " --no-fork Do not execute tests in a child process.  If this option is supplied\n"
  1726         "           and a test crashes (including by failing an assertion), no further\n"
  1727         "           tests will be performed.\n"
  1728  #endif
  1729         " --fatal-failures\n"
  1730         "           Stop executing tests as soon as a failure is found.\n"
  1731         " --show-stderr\n"
  1732         "           Show data written to stderr by the tests, even if the test succeeds.\n"
  1733         " --color auto|always|never\n"
  1734         "           Colorize (or don't) the output.\n"
  1735       /* 12345678901234567890123456789012345678901234567890123456789012345678901234567890 */
  1736         " --help    Print this help message and exit.\n");
  1737  #if defined(MUNIT_NL_LANGINFO)
  1738    setlocale(LC_ALL, "");
  1739    fputs((strcasecmp("UTF-8", nl_langinfo(CODESET)) == 0) ? "µnit" : "munit", stdout);
  1740  #else
  1741    puts("munit");
  1742  #endif
  1743    printf(" %d.%d.%d\n"
  1744           "Full documentation at: https://nemequ.github.io/munit/\n",
  1745           (MUNIT_CURRENT_VERSION >> 16) & 0xff,
  1746           (MUNIT_CURRENT_VERSION >> 8) & 0xff,
  1747           (MUNIT_CURRENT_VERSION >> 0) & 0xff);
  1748    for (arg = arguments ; arg != NULL && arg->name != NULL ; arg++)
  1749      arg->write_help(arg, user_data);
  1750  }
  1751  
  1752  static const MunitArgument*
  1753  munit_arguments_find(const MunitArgument arguments[], const char* name) {
  1754    const MunitArgument* arg;
  1755  
  1756    for (arg = arguments ; arg != NULL && arg->name != NULL ; arg++)
  1757      if (strcmp(arg->name, name) == 0)
  1758        return arg;
  1759  
  1760    return NULL;
  1761  }
  1762  
  1763  static void
  1764  munit_suite_list_tests(const MunitSuite* suite, munit_bool show_params, const char* prefix) {
  1765    size_t pre_l;
  1766    char* pre = munit_maybe_concat(&pre_l, (char*) prefix, (char*) suite->prefix);
  1767    const MunitTest* test;
  1768    const MunitParameterEnum* params;
  1769    munit_bool first;
  1770    char** val;
  1771    const MunitSuite* child_suite;
  1772  
  1773    for (test = suite->tests ;
  1774         test != NULL && test->name != NULL ;
  1775         test++) {
  1776      if (pre != NULL)
  1777        fputs(pre, stdout);
  1778      puts(test->name);
  1779  
  1780      if (show_params) {
  1781        for (params = test->parameters ;
  1782             params != NULL && params->name != NULL ;
  1783             params++) {
  1784          fprintf(stdout, " - %s: ", params->name);
  1785          if (params->values == NULL) {
  1786            puts("Any");
  1787          } else {
  1788            first = 1;
  1789            for (val = params->values ;
  1790                 *val != NULL ;
  1791                 val++ ) {
  1792              if(!first) {
  1793                fputs(", ", stdout);
  1794              } else {
  1795                first = 0;
  1796              }
  1797              fputs(*val, stdout);
  1798            }
  1799            putc('\n', stdout);
  1800          }
  1801        }
  1802      }
  1803    }
  1804  
  1805    for (child_suite = suite->suites ; child_suite != NULL && child_suite->prefix != NULL ; child_suite++) {
  1806      munit_suite_list_tests(child_suite, show_params, pre);
  1807    }
  1808  
  1809    munit_maybe_free_concat(pre, prefix, suite->prefix);
  1810  }
  1811  
  1812  static munit_bool
  1813  munit_stream_supports_ansi(FILE *stream) {
  1814  #if !defined(_WIN32)
  1815    return isatty(fileno(stream));
  1816  #else
  1817  
  1818  #if !defined(__MINGW32__)
  1819    size_t ansicon_size = 0;
  1820  #endif
  1821  
  1822    if (isatty(fileno(stream))) {
  1823  #if !defined(__MINGW32__)
  1824      getenv_s(&ansicon_size, NULL, 0, "ANSICON");
  1825      return ansicon_size != 0;
  1826  #else
  1827      return getenv("ANSICON") != NULL;
  1828  #endif
  1829    }
  1830    return 0;
  1831  #endif
  1832  }
  1833  
  1834  int
  1835  munit_suite_main_custom(const MunitSuite* suite, void* user_data,
  1836                          int argc, char* const argv[MUNIT_ARRAY_PARAM(argc + 1)],
  1837                          const MunitArgument arguments[]) {
  1838    int result = EXIT_FAILURE;
  1839    MunitTestRunner runner;
  1840    size_t parameters_size = 0;
  1841    size_t tests_size = 0;
  1842    int arg;
  1843  
  1844    char* envptr;
  1845    unsigned long ts;
  1846    char* endptr;
  1847    unsigned long long iterations;
  1848    MunitLogLevel level;
  1849    const MunitArgument* argument;
  1850    const char** runner_tests;
  1851    unsigned int tests_run;
  1852    unsigned int tests_total;
  1853  
  1854    runner.prefix = NULL;
  1855    runner.suite = NULL;
  1856    runner.tests = NULL;
  1857    runner.seed = 0;
  1858    runner.iterations = 0;
  1859    runner.parameters = NULL;
  1860    runner.single_parameter_mode = 0;
  1861    runner.user_data = NULL;
  1862  
  1863    runner.report.successful = 0;
  1864    runner.report.skipped = 0;
  1865    runner.report.failed = 0;
  1866    runner.report.errored = 0;
  1867  #if defined(MUNIT_ENABLE_TIMING)
  1868    runner.report.cpu_clock = 0;
  1869    runner.report.wall_clock = 0;
  1870  #endif
  1871  
  1872    runner.colorize = 0;
  1873  #if !defined(_WIN32)
  1874    runner.fork = 1;
  1875  #else
  1876    runner.fork = 0;
  1877  #endif
  1878    runner.show_stderr = 0;
  1879    runner.fatal_failures = 0;
  1880    runner.suite = suite;
  1881    runner.user_data = user_data;
  1882    runner.seed = munit_rand_generate_seed();
  1883    runner.colorize = munit_stream_supports_ansi(MUNIT_OUTPUT_FILE);
  1884  
  1885    for (arg = 1 ; arg < argc ; arg++) {
  1886      if (strncmp("--", argv[arg], 2) == 0) {
  1887        if (strcmp("seed", argv[arg] + 2) == 0) {
  1888          if (arg + 1 >= argc) {
  1889            munit_logf_internal(MUNIT_LOG_ERROR, stderr, "%s requires an argument", argv[arg]);
  1890            goto cleanup;
  1891          }
  1892  
  1893          envptr = argv[arg + 1];
  1894          ts = strtoul(argv[arg + 1], &envptr, 0);
  1895          if (*envptr != '\0' || ts > (~((munit_uint32_t) 0U))) {
  1896            munit_logf_internal(MUNIT_LOG_ERROR, stderr, "invalid value ('%s') passed to %s", argv[arg + 1], argv[arg]);
  1897            goto cleanup;
  1898          }
  1899          runner.seed = (munit_uint32_t) ts;
  1900  
  1901          arg++;
  1902        } else if (strcmp("iterations", argv[arg] + 2) == 0) {
  1903          if (arg + 1 >= argc) {
  1904            munit_logf_internal(MUNIT_LOG_ERROR, stderr, "%s requires an argument", argv[arg]);
  1905            goto cleanup;
  1906          }
  1907  
  1908          endptr = argv[arg + 1];
  1909          iterations = strtoul(argv[arg + 1], &endptr, 0);
  1910          if (*endptr != '\0' || iterations > UINT_MAX) {
  1911            munit_logf_internal(MUNIT_LOG_ERROR, stderr, "invalid value ('%s') passed to %s", argv[arg + 1], argv[arg]);
  1912            goto cleanup;
  1913          }
  1914  
  1915          runner.iterations = (unsigned int) iterations;
  1916  
  1917          arg++;
  1918        } else if (strcmp("param", argv[arg] + 2) == 0) {
  1919          if (arg + 2 >= argc) {
  1920            munit_logf_internal(MUNIT_LOG_ERROR, stderr, "%s requires two arguments", argv[arg]);
  1921            goto cleanup;
  1922          }
  1923  
  1924          runner.parameters = realloc(runner.parameters, sizeof(MunitParameter) * (parameters_size + 2));
  1925          if (runner.parameters == NULL) {
  1926            munit_log_internal(MUNIT_LOG_ERROR, stderr, "failed to allocate memory");
  1927            goto cleanup;
  1928          }
  1929          runner.parameters[parameters_size].name = (char*) argv[arg + 1];
  1930          runner.parameters[parameters_size].value = (char*) argv[arg + 2];
  1931          parameters_size++;
  1932          runner.parameters[parameters_size].name = NULL;
  1933          runner.parameters[parameters_size].value = NULL;
  1934          arg += 2;
  1935        } else if (strcmp("color", argv[arg] + 2) == 0) {
  1936          if (arg + 1 >= argc) {
  1937            munit_logf_internal(MUNIT_LOG_ERROR, stderr, "%s requires an argument", argv[arg]);
  1938            goto cleanup;
  1939          }
  1940  
  1941          if (strcmp(argv[arg + 1], "always") == 0)
  1942            runner.colorize = 1;
  1943          else if (strcmp(argv[arg + 1], "never") == 0)
  1944            runner.colorize = 0;
  1945          else if (strcmp(argv[arg + 1], "auto") == 0)
  1946            runner.colorize = munit_stream_supports_ansi(MUNIT_OUTPUT_FILE);
  1947          else {
  1948            munit_logf_internal(MUNIT_LOG_ERROR, stderr, "invalid value ('%s') passed to %s", argv[arg + 1], argv[arg]);
  1949            goto cleanup;
  1950          }
  1951  
  1952          arg++;
  1953        } else if (strcmp("help", argv[arg] + 2) == 0) {
  1954          munit_print_help(argc, argv, user_data, arguments);
  1955          result = EXIT_SUCCESS;
  1956          goto cleanup;
  1957        } else if (strcmp("single", argv[arg] + 2) == 0) {
  1958          runner.single_parameter_mode = 1;
  1959        } else if (strcmp("show-stderr", argv[arg] + 2) == 0) {
  1960          runner.show_stderr = 1;
  1961  #if !defined(_WIN32)
  1962        } else if (strcmp("no-fork", argv[arg] + 2) == 0) {
  1963          runner.fork = 0;
  1964  #endif
  1965        } else if (strcmp("fatal-failures", argv[arg] + 2) == 0) {
  1966          runner.fatal_failures = 1;
  1967        } else if (strcmp("log-visible", argv[arg] + 2) == 0 ||
  1968                   strcmp("log-fatal", argv[arg] + 2) == 0) {
  1969          if (arg + 1 >= argc) {
  1970            munit_logf_internal(MUNIT_LOG_ERROR, stderr, "%s requires an argument", argv[arg]);
  1971            goto cleanup;
  1972          }
  1973  
  1974          if (strcmp(argv[arg + 1], "debug") == 0)
  1975            level = MUNIT_LOG_DEBUG;
  1976          else if (strcmp(argv[arg + 1], "info") == 0)
  1977            level = MUNIT_LOG_INFO;
  1978          else if (strcmp(argv[arg + 1], "warning") == 0)
  1979            level = MUNIT_LOG_WARNING;
  1980          else if (strcmp(argv[arg + 1], "error") == 0)
  1981            level = MUNIT_LOG_ERROR;
  1982          else {
  1983            munit_logf_internal(MUNIT_LOG_ERROR, stderr, "invalid value ('%s') passed to %s", argv[arg + 1], argv[arg]);
  1984            goto cleanup;
  1985          }
  1986  
  1987          if (strcmp("log-visible", argv[arg] + 2) == 0)
  1988            munit_log_level_visible = level;
  1989          else
  1990            munit_log_level_fatal = level;
  1991  
  1992          arg++;
  1993        } else if (strcmp("list", argv[arg] + 2) == 0) {
  1994          munit_suite_list_tests(suite, 0, NULL);
  1995          result = EXIT_SUCCESS;
  1996          goto cleanup;
  1997        } else if (strcmp("list-params", argv[arg] + 2) == 0) {
  1998          munit_suite_list_tests(suite, 1, NULL);
  1999          result = EXIT_SUCCESS;
  2000          goto cleanup;
  2001        } else {
  2002          argument = munit_arguments_find(arguments, argv[arg] + 2);
  2003          if (argument == NULL) {
  2004            munit_logf_internal(MUNIT_LOG_ERROR, stderr, "unknown argument ('%s')", argv[arg]);
  2005            goto cleanup;
  2006          }
  2007  
  2008          if (!argument->parse_argument(suite, user_data, &arg, argc, argv))
  2009            goto cleanup;
  2010        }
  2011      } else {
  2012        runner_tests = realloc((void*) runner.tests, sizeof(char*) * (tests_size + 2));
  2013        if (runner_tests == NULL) {
  2014          munit_log_internal(MUNIT_LOG_ERROR, stderr, "failed to allocate memory");
  2015          goto cleanup;
  2016        }
  2017        runner.tests = runner_tests;
  2018        runner.tests[tests_size++] = argv[arg];
  2019        runner.tests[tests_size] = NULL;
  2020      }
  2021    }
  2022  
  2023    fflush(stderr);
  2024    fprintf(MUNIT_OUTPUT_FILE, "Running test suite with seed 0x%08" PRIx32 "...\n", runner.seed);
  2025  
  2026    munit_test_runner_run(&runner);
  2027  
  2028    tests_run = runner.report.successful + runner.report.failed + runner.report.errored;
  2029    tests_total = tests_run + runner.report.skipped;
  2030    if (tests_run == 0) {
  2031      fprintf(stderr, "No tests run, %d (100%%) skipped.\n", runner.report.skipped);
  2032    } else {
  2033      fprintf(MUNIT_OUTPUT_FILE, "%d of %d (%0.0f%%) tests successful, %d (%0.0f%%) test skipped.\n",
  2034              runner.report.successful, tests_run,
  2035              (((double) runner.report.successful) / ((double) tests_run)) * 100.0,
  2036              runner.report.skipped,
  2037              (((double) runner.report.skipped) / ((double) tests_total)) * 100.0);
  2038    }
  2039  
  2040    if (runner.report.failed == 0 && runner.report.errored == 0) {
  2041      result = EXIT_SUCCESS;
  2042    }
  2043  
  2044   cleanup:
  2045    free(runner.parameters);
  2046    free((void*) runner.tests);
  2047  
  2048    return result;
  2049  }
  2050  
  2051  int
  2052  munit_suite_main(const MunitSuite* suite, void* user_data,
  2053                   int argc, char* const argv[MUNIT_ARRAY_PARAM(argc + 1)]) {
  2054    return munit_suite_main_custom(suite, user_data, argc, argv, NULL);
  2055  }