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(¶ms_l, ¶ms, 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(¶ms_l, ¶ms, 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(¶ms_l, ¶ms, 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 }