utest.h (77635B)
1 /* 2 The latest version of this library is available on GitHub; 3 https://github.com/sheredom/utest.h 4 */ 5 6 /* 7 This is free and unencumbered software released into the public domain. 8 9 Anyone is free to copy, modify, publish, use, compile, sell, or 10 distribute this software, either in source code form or as a compiled 11 binary, for any purpose, commercial or non-commercial, and by any 12 means. 13 14 In jurisdictions that recognize copyright laws, the author or authors 15 of this software dedicate any and all copyright interest in the 16 software to the public domain. We make this dedication for the benefit 17 of the public at large and to the detriment of our heirs and 18 successors. We intend this dedication to be an overt act of 19 relinquishment in perpetuity of all present and future rights to this 20 software under copyright law. 21 22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 23 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 24 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 25 IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 26 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 27 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 28 OTHER DEALINGS IN THE SOFTWARE. 29 30 For more information, please refer to <http://unlicense.org/> 31 */ 32 33 #ifndef SHEREDOM_UTEST_H_INCLUDED 34 #define SHEREDOM_UTEST_H_INCLUDED 35 36 #ifdef _MSC_VER 37 /* 38 Disable warning about not inlining 'inline' functions. 39 */ 40 #pragma warning(disable : 4710) 41 42 /* 43 Disable warning about inlining functions that are not marked 'inline'. 44 */ 45 #pragma warning(disable : 4711) 46 47 /* 48 Disable warning for alignment padding added 49 */ 50 #pragma warning(disable : 4820) 51 52 #if _MSC_VER > 1900 53 /* 54 Disable warning about preprocessor macros not being defined in MSVC headers. 55 */ 56 #pragma warning(disable : 4668) 57 58 /* 59 Disable warning about no function prototype given in MSVC headers. 60 */ 61 #pragma warning(disable : 4255) 62 63 /* 64 Disable warning about pointer or reference to potentially throwing function. 65 */ 66 #pragma warning(disable : 5039) 67 68 /* 69 Disable warning about macro expansion producing 'defined' has undefined 70 behavior. 71 */ 72 #pragma warning(disable : 5105) 73 #endif 74 75 #if _MSC_VER > 1930 76 /* 77 Disable warning about 'const' variable is not used. 78 */ 79 #pragma warning(disable : 5264) 80 #endif 81 82 #pragma warning(push, 1) 83 #endif 84 85 #if defined(_MSC_VER) && (_MSC_VER < 1920) 86 typedef __int64 utest_int64_t; 87 typedef unsigned __int64 utest_uint64_t; 88 typedef unsigned __int32 utest_uint32_t; 89 #else 90 #include <stdint.h> 91 typedef int64_t utest_int64_t; 92 typedef uint64_t utest_uint64_t; 93 typedef uint32_t utest_uint32_t; 94 #endif 95 96 #include <stddef.h> 97 #include <stdio.h> 98 #include <stdlib.h> 99 #include <string.h> 100 #include <errno.h> 101 102 #if defined(__cplusplus) 103 #if defined(_MSC_VER) && !defined(_CPPUNWIND) 104 /* We're on MSVC and the compiler is compiling without exception support! */ 105 #elif !defined(_MSC_VER) && !defined(__EXCEPTIONS) 106 /* We're on a GCC/Clang compiler that doesn't have exception support! */ 107 #else 108 #define UTEST_HAS_EXCEPTIONS 1 109 #endif 110 #endif 111 112 #if defined(UTEST_HAS_EXCEPTIONS) 113 #include <stdexcept> 114 #endif 115 116 #if defined(_MSC_VER) 117 #pragma warning(pop) 118 #endif 119 120 #if defined(__cplusplus) 121 #define UTEST_C_FUNC extern "C" 122 #else 123 #define UTEST_C_FUNC 124 #endif 125 126 #define UTEST_TEST_PASSED (0) 127 #define UTEST_TEST_FAILURE (1) 128 #define UTEST_TEST_SKIPPED (2) 129 130 #if defined(__TINYC__) 131 #define UTEST_ATTRIBUTE(a) __attribute((a)) 132 #else 133 #define UTEST_ATTRIBUTE(a) __attribute__((a)) 134 #endif 135 136 #if defined(_MSC_VER) || defined(__MINGW64__) || defined(__MINGW32__) 137 138 #if defined(__MINGW64__) || defined(__MINGW32__) 139 #pragma GCC diagnostic push 140 #pragma GCC diagnostic ignored "-Wpragmas" 141 #pragma GCC diagnostic ignored "-Wunknown-pragmas" 142 #endif 143 144 #if defined(_WINDOWS_) || defined(_WINDOWS_H) 145 typedef LARGE_INTEGER utest_large_integer; 146 #else 147 // use old QueryPerformanceCounter definitions (not sure is this needed in some 148 // edge cases or not) on Win7 with VS2015 these extern declaration cause "second 149 // C linkage of overloaded function not allowed" error 150 typedef union { 151 struct { 152 unsigned long LowPart; 153 long HighPart; 154 } DUMMYSTRUCTNAME; 155 struct { 156 unsigned long LowPart; 157 long HighPart; 158 } u; 159 utest_int64_t QuadPart; 160 } utest_large_integer; 161 162 UTEST_C_FUNC __declspec(dllimport) int __stdcall QueryPerformanceCounter( 163 utest_large_integer *); 164 UTEST_C_FUNC __declspec(dllimport) int __stdcall QueryPerformanceFrequency( 165 utest_large_integer *); 166 167 #if defined(__MINGW64__) || defined(__MINGW32__) 168 #pragma GCC diagnostic pop 169 #endif 170 #endif 171 172 #elif defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || \ 173 defined(__NetBSD__) || defined(__DragonFly__) || defined(__sun__) || \ 174 defined(__HAIKU__) 175 /* 176 slightly obscure include here - we need to include glibc's features.h, but 177 we don't want to just include a header that might not be defined for other 178 c libraries like musl. Instead we include limits.h, which we know on all 179 glibc distributions includes features.h 180 */ 181 #include <limits.h> 182 183 #if defined(__GLIBC__) && defined(__GLIBC_MINOR__) 184 #include <time.h> 185 186 #if ((2 < __GLIBC__) || ((2 == __GLIBC__) && (17 <= __GLIBC_MINOR__))) 187 /* glibc is version 2.17 or above, so we can just use clock_gettime */ 188 #define UTEST_USE_CLOCKGETTIME 189 #else 190 #include <sys/syscall.h> 191 #include <unistd.h> 192 #endif 193 #else // Other libc implementations 194 #include <time.h> 195 #define UTEST_USE_CLOCKGETTIME 196 #endif 197 198 #elif defined(__APPLE__) 199 #include <time.h> 200 #endif 201 202 #if defined(_MSC_VER) && (_MSC_VER < 1920) 203 #define UTEST_PRId64 "I64d" 204 #define UTEST_PRIu64 "I64u" 205 #else 206 #include <inttypes.h> 207 208 #define UTEST_PRId64 PRId64 209 #define UTEST_PRIu64 PRIu64 210 #endif 211 212 #if defined(__cplusplus) 213 #define UTEST_INLINE inline 214 215 #if defined(__clang__) 216 #define UTEST_INITIALIZER_BEGIN_DISABLE_WARNINGS \ 217 _Pragma("clang diagnostic push") \ 218 _Pragma("clang diagnostic ignored \"-Wglobal-constructors\"") 219 220 #define UTEST_INITIALIZER_END_DISABLE_WARNINGS _Pragma("clang diagnostic pop") 221 #else 222 #define UTEST_INITIALIZER_BEGIN_DISABLE_WARNINGS 223 #define UTEST_INITIALIZER_END_DISABLE_WARNINGS 224 #endif 225 226 #define UTEST_INITIALIZER(f) \ 227 struct f##_cpp_struct { \ 228 f##_cpp_struct(); \ 229 }; \ 230 UTEST_INITIALIZER_BEGIN_DISABLE_WARNINGS static f##_cpp_struct \ 231 f##_cpp_global UTEST_INITIALIZER_END_DISABLE_WARNINGS; \ 232 f##_cpp_struct::f##_cpp_struct() 233 #elif defined(_MSC_VER) 234 #define UTEST_INLINE __forceinline 235 236 #if defined(_WIN64) 237 #define UTEST_SYMBOL_PREFIX 238 #else 239 #define UTEST_SYMBOL_PREFIX "_" 240 #endif 241 242 #if defined(__clang__) 243 #define UTEST_INITIALIZER_BEGIN_DISABLE_WARNINGS \ 244 _Pragma("clang diagnostic push") \ 245 _Pragma("clang diagnostic ignored \"-Wmissing-variable-declarations\"") 246 247 #define UTEST_INITIALIZER_END_DISABLE_WARNINGS _Pragma("clang diagnostic pop") 248 #else 249 #define UTEST_INITIALIZER_BEGIN_DISABLE_WARNINGS 250 #define UTEST_INITIALIZER_END_DISABLE_WARNINGS 251 #endif 252 253 #pragma section(".CRT$XCU", read) 254 #define UTEST_INITIALIZER(f) \ 255 static void __cdecl f(void); \ 256 UTEST_INITIALIZER_BEGIN_DISABLE_WARNINGS \ 257 __pragma(comment(linker, "/include:" UTEST_SYMBOL_PREFIX #f "_")) \ 258 UTEST_C_FUNC \ 259 __declspec(allocate(".CRT$XCU")) void(__cdecl * f##_)(void) = f; \ 260 UTEST_INITIALIZER_END_DISABLE_WARNINGS \ 261 static void __cdecl f(void) 262 #else 263 #if defined(__linux__) 264 #if defined(__clang__) 265 #if __has_warning("-Wreserved-id-macro") 266 #pragma clang diagnostic push 267 #pragma clang diagnostic ignored "-Wreserved-id-macro" 268 #endif 269 #endif 270 271 #define __STDC_FORMAT_MACROS 1 272 273 #if defined(__clang__) 274 #if __has_warning("-Wreserved-id-macro") 275 #pragma clang diagnostic pop 276 #endif 277 #endif 278 #endif 279 280 #define UTEST_INLINE inline 281 282 #define UTEST_INITIALIZER(f) \ 283 static void f(void) UTEST_ATTRIBUTE(constructor); \ 284 static void f(void) 285 #endif 286 287 #if defined(__cplusplus) 288 #define UTEST_CAST(type, x) static_cast<type>(x) 289 #define UTEST_PTR_CAST(type, x) reinterpret_cast<type>(x) 290 #define UTEST_EXTERN extern "C" 291 #define UTEST_NULL NULL 292 #else 293 #define UTEST_CAST(type, x) ((type)(x)) 294 #define UTEST_PTR_CAST(type, x) ((type)(x)) 295 #define UTEST_EXTERN extern 296 #define UTEST_NULL 0 297 #endif 298 299 #ifdef _MSC_VER 300 /* 301 io.h contains definitions for some structures with natural padding. This is 302 uninteresting, but for some reason MSVC's behaviour is to warn about 303 including this system header. That *is* interesting 304 */ 305 #pragma warning(disable : 4820) 306 #pragma warning(push, 1) 307 #include <io.h> 308 #pragma warning(pop) 309 #define UTEST_COLOUR_OUTPUT() (_isatty(_fileno(stdout))) 310 #else 311 #if defined(__EMSCRIPTEN__) 312 #include <emscripten/html5.h> 313 #define UTEST_COLOUR_OUTPUT() false 314 #else 315 #include <unistd.h> 316 #define UTEST_COLOUR_OUTPUT() (isatty(STDOUT_FILENO)) 317 #endif 318 #endif 319 320 static UTEST_INLINE void *utest_realloc(void *const pointer, size_t new_size) { 321 void *const new_pointer = realloc(pointer, new_size); 322 323 if (UTEST_NULL == new_pointer) { 324 free(pointer); 325 } 326 327 return new_pointer; 328 } 329 330 // Prevent 64-bit integer overflow when computing a timestamp by using a trick 331 // from Sokol: 332 // https://github.com/floooh/sokol/blob/189843bf4f86969ca4cc4b6d94e793a37c5128a7/sokol_time.h#L204 333 static UTEST_INLINE utest_int64_t utest_mul_div(const utest_int64_t value, 334 const utest_int64_t numer, 335 const utest_int64_t denom) { 336 const utest_int64_t q = value / denom; 337 const utest_int64_t r = value % denom; 338 return q * numer + r * numer / denom; 339 } 340 341 static UTEST_INLINE utest_int64_t utest_ns(void) { 342 #if defined(_MSC_VER) || defined(__MINGW64__) || defined(__MINGW32__) 343 utest_large_integer counter; 344 utest_large_integer frequency; 345 QueryPerformanceCounter(&counter); 346 QueryPerformanceFrequency(&frequency); 347 return utest_mul_div(counter.QuadPart, 1000000000, frequency.QuadPart); 348 #elif defined(__linux__) && defined(__STRICT_ANSI__) 349 return utest_mul_div(clock(), 1000000000, CLOCKS_PER_SEC); 350 #elif defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) || \ 351 defined(__NetBSD__) || defined(__DragonFly__) || defined(__sun__) || \ 352 defined(__HAIKU__) 353 struct timespec ts; 354 #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && \ 355 !defined(__HAIKU__) 356 timespec_get(&ts, TIME_UTC); 357 #else 358 const clockid_t cid = CLOCK_REALTIME; 359 #if defined(UTEST_USE_CLOCKGETTIME) 360 clock_gettime(cid, &ts); 361 #else 362 syscall(SYS_clock_gettime, cid, &ts); 363 #endif 364 #endif 365 return UTEST_CAST(utest_int64_t, ts.tv_sec) * 1000 * 1000 * 1000 + ts.tv_nsec; 366 #elif __APPLE__ 367 return UTEST_CAST(utest_int64_t, clock_gettime_nsec_np(CLOCK_UPTIME_RAW)); 368 #elif __EMSCRIPTEN__ 369 return emscripten_performance_now() * 1000000.0; 370 #else 371 #error Unsupported platform! 372 #endif 373 } 374 375 typedef void (*utest_testcase_t)(int *, size_t); 376 377 struct utest_test_state_s { 378 utest_testcase_t func; 379 size_t index; 380 char *name; 381 }; 382 383 struct utest_state_s { 384 struct utest_test_state_s *tests; 385 size_t tests_length; 386 FILE *output; 387 }; 388 389 /* extern to the global state utest needs to execute */ 390 UTEST_EXTERN struct utest_state_s utest_state; 391 392 #if defined(_MSC_VER) 393 #define UTEST_WEAK __forceinline 394 #elif defined(__MINGW32__) || defined(__MINGW64__) 395 #define UTEST_WEAK static UTEST_ATTRIBUTE(used) 396 #elif defined(__clang__) || defined(__GNUC__) || defined(__TINYC__) 397 #define UTEST_WEAK UTEST_ATTRIBUTE(weak) 398 #else 399 #error Non clang, non gcc, non MSVC, non tcc compiler found! 400 #endif 401 402 #if defined(_MSC_VER) 403 #define UTEST_UNUSED 404 #else 405 #define UTEST_UNUSED UTEST_ATTRIBUTE(unused) 406 #endif 407 408 #ifdef __clang__ 409 #pragma clang diagnostic push 410 #pragma clang diagnostic ignored "-Wvariadic-macros" 411 #pragma clang diagnostic ignored "-Wc++98-compat-pedantic" 412 #endif 413 #define UTEST_PRINTF(...) \ 414 if (utest_state.output) { \ 415 fprintf(utest_state.output, __VA_ARGS__); \ 416 } \ 417 printf(__VA_ARGS__) 418 #ifdef __clang__ 419 #pragma clang diagnostic pop 420 #endif 421 422 #ifdef __clang__ 423 #pragma clang diagnostic push 424 #pragma clang diagnostic ignored "-Wvariadic-macros" 425 #pragma clang diagnostic ignored "-Wc++98-compat-pedantic" 426 #endif 427 428 #ifdef _MSC_VER 429 #define UTEST_SNPRINTF(BUFFER, N, ...) _snprintf_s(BUFFER, N, N, __VA_ARGS__) 430 #else 431 #define UTEST_SNPRINTF(...) snprintf(__VA_ARGS__) 432 #endif 433 434 #ifdef __clang__ 435 #pragma clang diagnostic pop 436 #endif 437 438 #if defined(__cplusplus) 439 /* if we are using c++ we can use overloaded methods (its in the language) */ 440 #define UTEST_OVERLOADABLE 441 #elif defined(__clang__) 442 /* otherwise, if we are using clang with c - use the overloadable attribute */ 443 #define UTEST_OVERLOADABLE UTEST_ATTRIBUTE(overloadable) 444 #endif 445 446 #if defined(__cplusplus) && (__cplusplus >= 201103L) 447 448 #ifdef __clang__ 449 #pragma clang diagnostic push 450 #pragma clang diagnostic ignored "-Wc++98-compat-pedantic" 451 #endif 452 453 #include <type_traits> 454 455 template <typename T, bool is_enum = std::is_enum<T>::value> 456 struct utest_type_deducer final { 457 static void _(const T t); 458 }; 459 460 template <> struct utest_type_deducer<char, false> { 461 static void _(const char c) { 462 if (std::is_signed<decltype(c)>::value) { 463 UTEST_PRINTF("%d", static_cast<int>(c)); 464 } else { 465 UTEST_PRINTF("%u", static_cast<unsigned int>(c)); 466 } 467 } 468 }; 469 template <> struct utest_type_deducer<signed char, false> { 470 static void _(const signed char c) { 471 UTEST_PRINTF("%d", static_cast<int>(c)); 472 } 473 }; 474 475 template <> struct utest_type_deducer<unsigned char, false> { 476 static void _(const unsigned char c) { 477 UTEST_PRINTF("%u", static_cast<unsigned int>(c)); 478 } 479 }; 480 481 template <> struct utest_type_deducer<short, false> { 482 static void _(const short s) { UTEST_PRINTF("%d", static_cast<int>(s)); } 483 }; 484 485 template <> struct utest_type_deducer<unsigned short, false> { 486 static void _(const unsigned short s) { 487 UTEST_PRINTF("%u", static_cast<unsigned>(s)); 488 } 489 }; 490 491 template <> struct utest_type_deducer<float, false> { 492 static void _(const float f) { UTEST_PRINTF("%f", static_cast<double>(f)); } 493 }; 494 495 template <> struct utest_type_deducer<double, false> { 496 static void _(const double d) { UTEST_PRINTF("%f", d); } 497 }; 498 499 template <> struct utest_type_deducer<long double, false> { 500 static void _(const long double d) { 501 #if defined(__MINGW32__) || defined(__MINGW64__) 502 /* MINGW is weird - doesn't like LF at all?! */ 503 UTEST_PRINTF("%f", (double)d); 504 #else 505 UTEST_PRINTF("%Lf", d); 506 #endif 507 } 508 }; 509 510 template <> struct utest_type_deducer<int, false> { 511 static void _(const int i) { UTEST_PRINTF("%d", i); } 512 }; 513 514 template <> struct utest_type_deducer<unsigned int, false> { 515 static void _(const unsigned int i) { UTEST_PRINTF("%u", i); } 516 }; 517 518 template <> struct utest_type_deducer<long, false> { 519 static void _(const long i) { UTEST_PRINTF("%ld", i); } 520 }; 521 522 template <> struct utest_type_deducer<unsigned long, false> { 523 static void _(const unsigned long i) { UTEST_PRINTF("%lu", i); } 524 }; 525 526 template <> struct utest_type_deducer<long long, false> { 527 static void _(const long long i) { UTEST_PRINTF("%lld", i); } 528 }; 529 530 template <> struct utest_type_deducer<unsigned long long, false> { 531 static void _(const unsigned long long i) { UTEST_PRINTF("%llu", i); } 532 }; 533 534 template <> struct utest_type_deducer<bool, false> { 535 static void _(const bool i) { UTEST_PRINTF(i ? "true" : "false"); } 536 }; 537 538 template <typename T> struct utest_type_deducer<const T *, false> { 539 static void _(const T *t) { 540 UTEST_PRINTF("%p", static_cast<void *>(const_cast<T *>(t))); 541 } 542 }; 543 544 template <typename T> struct utest_type_deducer<T *, false> { 545 static void _(T *t) { UTEST_PRINTF("%p", static_cast<void *>(t)); } 546 }; 547 548 template <typename T> struct utest_type_deducer<T, true> { 549 static void _(const T t) { 550 UTEST_PRINTF("%llu", static_cast<unsigned long long>(t)); 551 } 552 }; 553 554 template <> struct utest_type_deducer<std::nullptr_t, false> { 555 static void _(std::nullptr_t t) { 556 UTEST_PRINTF("%p", static_cast<void *>(t)); 557 } 558 }; 559 560 template <typename T> 561 UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(const T t) { 562 utest_type_deducer<T>::_(t); 563 } 564 565 #ifdef __clang__ 566 #pragma clang diagnostic pop 567 #endif 568 569 #elif defined(UTEST_OVERLOADABLE) 570 571 UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(signed char c); 572 UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(signed char c) { 573 UTEST_PRINTF("%d", UTEST_CAST(int, c)); 574 } 575 576 UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(unsigned char c); 577 UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(unsigned char c) { 578 UTEST_PRINTF("%u", UTEST_CAST(unsigned int, c)); 579 } 580 581 UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(float f); 582 UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(float f) { 583 UTEST_PRINTF("%f", UTEST_CAST(double, f)); 584 } 585 586 UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(double d); 587 UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(double d) { 588 UTEST_PRINTF("%f", d); 589 } 590 591 UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(long double d); 592 UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(long double d) { 593 #if defined(__MINGW32__) || defined(__MINGW64__) 594 /* MINGW is weird - doesn't like LF at all?! */ 595 UTEST_PRINTF("%f", (double)d); 596 #else 597 UTEST_PRINTF("%Lf", d); 598 #endif 599 } 600 601 UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(int i); 602 UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(int i) { 603 UTEST_PRINTF("%d", i); 604 } 605 606 UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(unsigned int i); 607 UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(unsigned int i) { 608 UTEST_PRINTF("%u", i); 609 } 610 611 UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(long int i); 612 UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(long int i) { 613 UTEST_PRINTF("%ld", i); 614 } 615 616 UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(long unsigned int i); 617 UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(long unsigned int i) { 618 UTEST_PRINTF("%lu", i); 619 } 620 621 UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(const void *p); 622 UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(const void *p) { 623 UTEST_PRINTF("%p", p); 624 } 625 626 /* 627 long long is a c++11 extension 628 */ 629 #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) || \ 630 defined(__cplusplus) && (__cplusplus >= 201103L) || \ 631 (defined(__MINGW32__) || defined(__MINGW64__)) 632 633 #ifdef __clang__ 634 #pragma clang diagnostic push 635 #pragma clang diagnostic ignored "-Wc++98-compat-pedantic" 636 #endif 637 638 UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(long long int i); 639 UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(long long int i) { 640 UTEST_PRINTF("%lld", i); 641 } 642 643 UTEST_WEAK UTEST_OVERLOADABLE void utest_type_printer(long long unsigned int i); 644 UTEST_WEAK UTEST_OVERLOADABLE void 645 utest_type_printer(long long unsigned int i) { 646 UTEST_PRINTF("%llu", i); 647 } 648 649 #ifdef __clang__ 650 #pragma clang diagnostic pop 651 #endif 652 653 #endif 654 #elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && \ 655 !(defined(__MINGW32__) || defined(__MINGW64__)) || \ 656 defined(__TINYC__) 657 #define utest_type_printer(val) \ 658 UTEST_PRINTF( \ 659 _Generic((val), \ 660 signed char: "%d", \ 661 unsigned char: "%u", \ 662 short: "%d", \ 663 unsigned short: "%u", \ 664 int: "%d", \ 665 long: "%ld", \ 666 long long: "%lld", \ 667 unsigned: "%u", \ 668 unsigned long: "%lu", \ 669 unsigned long long: "%llu", \ 670 float: "%f", \ 671 double: "%f", \ 672 long double: "%Lf", \ 673 default: _Generic((val - val), ptrdiff_t: "%p", default: "undef")), \ 674 (val)) 675 #else 676 /* 677 we don't have the ability to print the values we got, so we create a macro 678 to tell our users we can't do anything fancy 679 */ 680 #define utest_type_printer(...) UTEST_PRINTF("undef") 681 #endif 682 683 #if defined(_MSC_VER) 684 #define UTEST_SURPRESS_WARNING_BEGIN \ 685 __pragma(warning(push)) __pragma(warning(disable : 4127)) \ 686 __pragma(warning(disable : 4571)) __pragma(warning(disable : 4130)) 687 #define UTEST_SURPRESS_WARNING_END __pragma(warning(pop)) 688 #else 689 #define UTEST_SURPRESS_WARNING_BEGIN 690 #define UTEST_SURPRESS_WARNING_END 691 #endif 692 693 #if defined(__cplusplus) && (__cplusplus >= 201103L) 694 #define UTEST_AUTO(x) auto 695 #elif !defined(__cplusplus) 696 697 #if defined(__clang__) 698 /* clang-format off */ 699 /* had to disable clang-format here because it malforms the pragmas */ 700 #define UTEST_AUTO(x) \ 701 _Pragma("clang diagnostic push") \ 702 _Pragma("clang diagnostic ignored \"-Wgnu-auto-type\"") __auto_type \ 703 _Pragma("clang diagnostic pop") 704 /* clang-format on */ 705 #else 706 #define UTEST_AUTO(x) __typeof__(x + 0) 707 #endif 708 709 #else 710 #define UTEST_AUTO(x) typeof(x + 0) 711 #endif 712 713 #if defined(__clang__) 714 #define UTEST_STRNCMP(x, y, size) \ 715 _Pragma("clang diagnostic push") \ 716 _Pragma("clang diagnostic ignored \"-Wdisabled-macro-expansion\"") \ 717 strncmp(x, y, size) _Pragma("clang diagnostic pop") 718 #else 719 #define UTEST_STRNCMP(x, y, size) strncmp(x, y, size) 720 #endif 721 722 #if defined(_MSC_VER) 723 #define UTEST_STRNCPY(x, y, size) strcpy_s(x, size, y) 724 #elif !defined(__clang__) && defined(__GNUC__) 725 static UTEST_INLINE char * 726 utest_strncpy_gcc(char *const dst, const char *const src, const size_t size) { 727 #pragma GCC diagnostic push 728 #pragma GCC diagnostic ignored "-Wstringop-overflow" 729 return strncpy(dst, src, size); 730 #pragma GCC diagnostic pop 731 } 732 733 #define UTEST_STRNCPY(x, y, size) utest_strncpy_gcc(x, y, size) 734 #else 735 #define UTEST_STRNCPY(x, y, size) strncpy(x, y, size) 736 #endif 737 738 #define UTEST_SKIP(msg) \ 739 do { \ 740 UTEST_PRINTF(" Skipped : '%s'\n", (msg)); \ 741 *utest_result = UTEST_TEST_SKIPPED; \ 742 return; \ 743 } while (0) 744 745 #if defined(__clang__) 746 #define UTEST_COND(x, y, cond, msg, is_assert) \ 747 UTEST_SURPRESS_WARNING_BEGIN do { \ 748 _Pragma("clang diagnostic push") \ 749 _Pragma("clang diagnostic ignored \"-Wlanguage-extension-token\"") \ 750 _Pragma("clang diagnostic ignored \"-Wc++98-compat-pedantic\"") \ 751 _Pragma("clang diagnostic ignored \"-Wfloat-equal\"") \ 752 UTEST_AUTO(x) xEval = (x); \ 753 UTEST_AUTO(y) yEval = (y); \ 754 if (!((xEval)cond(yEval))) { \ 755 const char *const xAsString = #x; \ 756 const char *const yAsString = #y; \ 757 _Pragma("clang diagnostic pop") \ 758 UTEST_PRINTF("%s:%i: Failure\n", __FILE__, __LINE__); \ 759 UTEST_PRINTF(" Expected : ("); \ 760 UTEST_PRINTF("%s) " #cond " (%s", xAsString, yAsString); \ 761 UTEST_PRINTF(")\n"); \ 762 UTEST_PRINTF(" Actual : "); \ 763 utest_type_printer(xEval); \ 764 UTEST_PRINTF(" vs "); \ 765 utest_type_printer(yEval); \ 766 UTEST_PRINTF("\n"); \ 767 if (strlen(msg) > 0) { \ 768 UTEST_PRINTF(" Message : %s\n", msg); \ 769 } \ 770 *utest_result = UTEST_TEST_FAILURE; \ 771 if (is_assert) { \ 772 return; \ 773 } \ 774 } \ 775 } \ 776 while (0) \ 777 UTEST_SURPRESS_WARNING_END 778 #elif defined(__GNUC__) || defined(__TINYC__) 779 #define UTEST_COND(x, y, cond, msg, is_assert) \ 780 UTEST_SURPRESS_WARNING_BEGIN do { \ 781 UTEST_AUTO(x) xEval = (x); \ 782 UTEST_AUTO(y) yEval = (y); \ 783 if (!((xEval)cond(yEval))) { \ 784 const char *const xAsString = #x; \ 785 const char *const yAsString = #y; \ 786 UTEST_PRINTF("%s:%i: Failure\n", __FILE__, __LINE__); \ 787 UTEST_PRINTF(" Expected : ("); \ 788 UTEST_PRINTF("%s) " #cond " (%s", xAsString, yAsString); \ 789 UTEST_PRINTF(")\n"); \ 790 UTEST_PRINTF(" Actual : "); \ 791 utest_type_printer(xEval); \ 792 UTEST_PRINTF(" vs "); \ 793 utest_type_printer(yEval); \ 794 UTEST_PRINTF("\n"); \ 795 if (strlen(msg) > 0) { \ 796 UTEST_PRINTF(" Message : %s\n", msg); \ 797 } \ 798 *utest_result = UTEST_TEST_FAILURE; \ 799 if (is_assert) { \ 800 return; \ 801 } \ 802 } \ 803 } \ 804 while (0) \ 805 UTEST_SURPRESS_WARNING_END 806 #else 807 #define UTEST_COND(x, y, cond, msg, is_assert) \ 808 UTEST_SURPRESS_WARNING_BEGIN do { \ 809 if (!((x)cond(y))) { \ 810 UTEST_PRINTF("%s:%i: Failure (Expected " #cond " Actual)", __FILE__, \ 811 __LINE__); \ 812 if (strlen(msg) > 0) { \ 813 UTEST_PRINTF(" Message : %s", msg); \ 814 } \ 815 UTEST_PRINTF("\n"); \ 816 *utest_result = UTEST_TEST_FAILURE; \ 817 if (is_assert) { \ 818 return; \ 819 } \ 820 } \ 821 } \ 822 while (0) \ 823 UTEST_SURPRESS_WARNING_END 824 #endif 825 826 #define EXPECT_EQ(x, y) UTEST_COND(x, y, ==, "", 0) 827 #define EXPECT_EQ_MSG(x, y, msg) UTEST_COND(x, y, ==, msg, 0) 828 #define ASSERT_EQ(x, y) UTEST_COND(x, y, ==, "", 1) 829 #define ASSERT_EQ_MSG(x, y, msg) UTEST_COND(x, y, ==, msg, 1) 830 831 #define EXPECT_NE(x, y) UTEST_COND(x, y, !=, "", 0) 832 #define EXPECT_NE_MSG(x, y, msg) UTEST_COND(x, y, !=, msg, 0) 833 #define ASSERT_NE(x, y) UTEST_COND(x, y, !=, "", 1) 834 #define ASSERT_NE_MSG(x, y, msg) UTEST_COND(x, y, !=, msg, 1) 835 836 #define EXPECT_LT(x, y) UTEST_COND(x, y, <, "", 0) 837 #define EXPECT_LT_MSG(x, y, msg) UTEST_COND(x, y, <, msg, 0) 838 #define ASSERT_LT(x, y) UTEST_COND(x, y, <, "", 1) 839 #define ASSERT_LT_MSG(x, y, msg) UTEST_COND(x, y, <, msg, 1) 840 841 #define EXPECT_LE(x, y) UTEST_COND(x, y, <=, "", 0) 842 #define EXPECT_LE_MSG(x, y, msg) UTEST_COND(x, y, <=, msg, 0) 843 #define ASSERT_LE(x, y) UTEST_COND(x, y, <=, "", 1) 844 #define ASSERT_LE_MSG(x, y, msg) UTEST_COND(x, y, <=, msg, 1) 845 846 #define EXPECT_GT(x, y) UTEST_COND(x, y, >, "", 0) 847 #define EXPECT_GT_MSG(x, y, msg) UTEST_COND(x, y, >, msg, 0) 848 #define ASSERT_GT(x, y) UTEST_COND(x, y, >, "", 1) 849 #define ASSERT_GT_MSG(x, y, msg) UTEST_COND(x, y, >, msg, 1) 850 851 #define EXPECT_GE(x, y) UTEST_COND(x, y, >=, "", 0) 852 #define EXPECT_GE_MSG(x, y, msg) UTEST_COND(x, y, >=, msg, 0) 853 #define ASSERT_GE(x, y) UTEST_COND(x, y, >=, "", 1) 854 #define ASSERT_GE_MSG(x, y, msg) UTEST_COND(x, y, >=, msg, 1) 855 856 #define UTEST_TRUE(x, msg, is_assert) \ 857 UTEST_SURPRESS_WARNING_BEGIN do { \ 858 const int xEval = !!(x); \ 859 if (!(xEval)) { \ 860 UTEST_PRINTF("%s:%i: Failure\n", __FILE__, __LINE__); \ 861 UTEST_PRINTF(" Expected : true\n"); \ 862 UTEST_PRINTF(" Actual : %s\n", (xEval) ? "true" : "false"); \ 863 if (strlen(msg) > 0) { \ 864 UTEST_PRINTF(" Message : %s\n", msg); \ 865 } \ 866 *utest_result = UTEST_TEST_FAILURE; \ 867 if (is_assert) { \ 868 return; \ 869 } \ 870 } \ 871 } \ 872 while (0) \ 873 UTEST_SURPRESS_WARNING_END 874 875 #define EXPECT_TRUE(x) UTEST_TRUE(x, "", 0) 876 #define EXPECT_TRUE_MSG(x, msg) UTEST_TRUE(x, msg, 0) 877 #define ASSERT_TRUE(x) UTEST_TRUE(x, "", 1) 878 #define ASSERT_TRUE_MSG(x, msg) UTEST_TRUE(x, msg, 1) 879 880 #define UTEST_FALSE(x, msg, is_assert) \ 881 UTEST_SURPRESS_WARNING_BEGIN do { \ 882 const int xEval = !!(x); \ 883 if (xEval) { \ 884 UTEST_PRINTF("%s:%i: Failure\n", __FILE__, __LINE__); \ 885 UTEST_PRINTF(" Expected : false\n"); \ 886 UTEST_PRINTF(" Actual : %s\n", (xEval) ? "true" : "false"); \ 887 if (strlen(msg) > 0) { \ 888 UTEST_PRINTF(" Message : %s\n", msg); \ 889 } \ 890 *utest_result = UTEST_TEST_FAILURE; \ 891 if (is_assert) { \ 892 return; \ 893 } \ 894 } \ 895 } \ 896 while (0) \ 897 UTEST_SURPRESS_WARNING_END 898 899 #define EXPECT_FALSE(x) UTEST_FALSE(x, "", 0) 900 #define EXPECT_FALSE_MSG(x, msg) UTEST_FALSE(x, msg, 0) 901 #define ASSERT_FALSE(x) UTEST_FALSE(x, "", 1) 902 #define ASSERT_FALSE_MSG(x, msg) UTEST_FALSE(x, msg, 1) 903 904 #define UTEST_STREQ(x, y, msg, is_assert) \ 905 UTEST_SURPRESS_WARNING_BEGIN do { \ 906 const char *xEval = (x); \ 907 const char *yEval = (y); \ 908 if (UTEST_NULL == xEval || UTEST_NULL == yEval || \ 909 0 != strcmp(xEval, yEval)) { \ 910 UTEST_PRINTF("%s:%i: Failure\n", __FILE__, __LINE__); \ 911 UTEST_PRINTF(" Expected : \"%s\"\n", xEval); \ 912 UTEST_PRINTF(" Actual : \"%s\"\n", yEval); \ 913 if (strlen(msg) > 0) { \ 914 UTEST_PRINTF(" Message : %s\n", msg); \ 915 } \ 916 *utest_result = UTEST_TEST_FAILURE; \ 917 if (is_assert) { \ 918 return; \ 919 } \ 920 } \ 921 } \ 922 while (0) \ 923 UTEST_SURPRESS_WARNING_END 924 925 #define EXPECT_STREQ(x, y) UTEST_STREQ(x, y, "", 0) 926 #define EXPECT_STREQ_MSG(x, y, msg) UTEST_STREQ(x, y, msg, 0) 927 #define ASSERT_STREQ(x, y) UTEST_STREQ(x, y, "", 1) 928 #define ASSERT_STREQ_MSG(x, y, msg) UTEST_STREQ(x, y, msg, 1) 929 930 #define UTEST_STRNE(x, y, msg, is_assert) \ 931 UTEST_SURPRESS_WARNING_BEGIN do { \ 932 const char *xEval = (x); \ 933 const char *yEval = (y); \ 934 if (UTEST_NULL == xEval || UTEST_NULL == yEval || \ 935 0 == strcmp(xEval, yEval)) { \ 936 UTEST_PRINTF("%s:%i: Failure\n", __FILE__, __LINE__); \ 937 UTEST_PRINTF(" Expected : \"%s\"\n", xEval); \ 938 UTEST_PRINTF(" Actual : \"%s\"\n", yEval); \ 939 if (strlen(msg) > 0) { \ 940 UTEST_PRINTF(" Message : %s\n", msg); \ 941 } \ 942 *utest_result = UTEST_TEST_FAILURE; \ 943 if (is_assert) { \ 944 return; \ 945 } \ 946 } \ 947 } \ 948 while (0) \ 949 UTEST_SURPRESS_WARNING_END 950 951 #define EXPECT_STRNE(x, y) UTEST_STRNE(x, y, "", 0) 952 #define EXPECT_STRNE_MSG(x, y, msg) UTEST_STRNE(x, y, msg, 0) 953 #define ASSERT_STRNE(x, y) UTEST_STRNE(x, y, "", 1) 954 #define ASSERT_STRNE_MSG(x, y, msg) UTEST_STRNE(x, y, msg, 1) 955 956 #define UTEST_STRNEQ(x, y, n, msg, is_assert) \ 957 UTEST_SURPRESS_WARNING_BEGIN do { \ 958 const char *xEval = (x); \ 959 const char *yEval = (y); \ 960 const size_t nEval = UTEST_CAST(size_t, n); \ 961 if (UTEST_NULL == xEval || UTEST_NULL == yEval || \ 962 0 != UTEST_STRNCMP(xEval, yEval, nEval)) { \ 963 UTEST_PRINTF("%s:%i: Failure\n", __FILE__, __LINE__); \ 964 UTEST_PRINTF(" Expected : \"%.*s\"\n", UTEST_CAST(int, nEval), xEval); \ 965 UTEST_PRINTF(" Actual : \"%.*s\"\n", UTEST_CAST(int, nEval), yEval); \ 966 if (strlen(msg) > 0) { \ 967 UTEST_PRINTF(" Message : %s\n", msg); \ 968 } \ 969 *utest_result = UTEST_TEST_FAILURE; \ 970 if (is_assert) { \ 971 return; \ 972 } \ 973 } \ 974 } \ 975 while (0) \ 976 UTEST_SURPRESS_WARNING_END 977 978 #define EXPECT_STRNEQ(x, y, n) UTEST_STRNEQ(x, y, n, "", 0) 979 #define EXPECT_STRNEQ_MSG(x, y, n, msg) UTEST_STRNEQ(x, y, n, msg, 0) 980 #define ASSERT_STRNEQ(x, y, n) UTEST_STRNEQ(x, y, n, "", 1) 981 #define ASSERT_STRNEQ_MSG(x, y, n, msg) UTEST_STRNEQ(x, y, n, msg, 1) 982 983 #define UTEST_STRNNE(x, y, n, msg, is_assert) \ 984 UTEST_SURPRESS_WARNING_BEGIN do { \ 985 const char *xEval = (x); \ 986 const char *yEval = (y); \ 987 const size_t nEval = UTEST_CAST(size_t, n); \ 988 if (UTEST_NULL == xEval || UTEST_NULL == yEval || \ 989 0 == UTEST_STRNCMP(xEval, yEval, nEval)) { \ 990 UTEST_PRINTF("%s:%i: Failure\n", __FILE__, __LINE__); \ 991 UTEST_PRINTF(" Expected : \"%.*s\"\n", UTEST_CAST(int, nEval), xEval); \ 992 UTEST_PRINTF(" Actual : \"%.*s\"\n", UTEST_CAST(int, nEval), yEval); \ 993 if (strlen(msg) > 0) { \ 994 UTEST_PRINTF(" Message : %s\n", msg); \ 995 } \ 996 *utest_result = UTEST_TEST_FAILURE; \ 997 if (is_assert) { \ 998 return; \ 999 } \ 1000 } \ 1001 } \ 1002 while (0) \ 1003 UTEST_SURPRESS_WARNING_END 1004 1005 #define EXPECT_STRNNE(x, y, n) UTEST_STRNNE(x, y, n, "", 0) 1006 #define EXPECT_STRNNE_MSG(x, y, n, msg) UTEST_STRNNE(x, y, n, msg, 0) 1007 #define ASSERT_STRNNE(x, y, n) UTEST_STRNNE(x, y, n, "", 1) 1008 #define ASSERT_STRNNE_MSG(x, y, n, msg) UTEST_STRNNE(x, y, n, msg, 1) 1009 1010 #define UTEST_NEAR(x, y, epsilon, msg, is_assert) \ 1011 UTEST_SURPRESS_WARNING_BEGIN do { \ 1012 const double diff = \ 1013 utest_fabs(UTEST_CAST(double, x) - UTEST_CAST(double, y)); \ 1014 if (diff > UTEST_CAST(double, epsilon) || utest_isnan(diff)) { \ 1015 UTEST_PRINTF("%s:%i: Failure\n", __FILE__, __LINE__); \ 1016 UTEST_PRINTF(" Expected : %f\n", UTEST_CAST(double, x)); \ 1017 UTEST_PRINTF(" Actual : %f\n", UTEST_CAST(double, y)); \ 1018 if (strlen(msg) > 0) { \ 1019 UTEST_PRINTF(" Message : %s\n", msg); \ 1020 } \ 1021 *utest_result = UTEST_TEST_FAILURE; \ 1022 if (is_assert) { \ 1023 return; \ 1024 } \ 1025 } \ 1026 } \ 1027 while (0) \ 1028 UTEST_SURPRESS_WARNING_END 1029 1030 #define EXPECT_NEAR(x, y, epsilon) UTEST_NEAR(x, y, epsilon, "", 0) 1031 #define EXPECT_NEAR_MSG(x, y, epsilon, msg) UTEST_NEAR(x, y, epsilon, msg, 0) 1032 #define ASSERT_NEAR(x, y, epsilon) UTEST_NEAR(x, y, epsilon, "", 1) 1033 #define ASSERT_NEAR_MSG(x, y, epsilon, msg) UTEST_NEAR(x, y, epsilon, msg, 1) 1034 1035 #if defined(UTEST_HAS_EXCEPTIONS) 1036 #define UTEST_EXCEPTION(x, exception_type, msg, is_assert) \ 1037 UTEST_SURPRESS_WARNING_BEGIN do { \ 1038 int exception_caught = 0; \ 1039 try { \ 1040 x; \ 1041 } catch (const exception_type &) { \ 1042 exception_caught = 1; \ 1043 } catch (...) { \ 1044 exception_caught = 2; \ 1045 } \ 1046 if (1 != exception_caught) { \ 1047 UTEST_PRINTF("%s:%i: Failure\n", __FILE__, __LINE__); \ 1048 UTEST_PRINTF(" Expected : %s exception\n", #exception_type); \ 1049 UTEST_PRINTF(" Actual : %s\n", (2 == exception_caught) \ 1050 ? "Unexpected exception" \ 1051 : "No exception"); \ 1052 if (strlen(msg) > 0) { \ 1053 UTEST_PRINTF(" Message : %s\n", msg); \ 1054 } \ 1055 *utest_result = UTEST_TEST_FAILURE; \ 1056 if (is_assert) { \ 1057 return; \ 1058 } \ 1059 } \ 1060 } \ 1061 while (0) \ 1062 UTEST_SURPRESS_WARNING_END 1063 1064 #define EXPECT_EXCEPTION(x, exception_type) \ 1065 UTEST_EXCEPTION(x, exception_type, "", 0) 1066 #define EXPECT_EXCEPTION_MSG(x, exception_type, msg) \ 1067 UTEST_EXCEPTION(x, exception_type, msg, 0) 1068 #define ASSERT_EXCEPTION(x, exception_type) \ 1069 UTEST_EXCEPTION(x, exception_type, "", 1) 1070 #define ASSERT_EXCEPTION_MSG(x, exception_type, msg) \ 1071 UTEST_EXCEPTION(x, exception_type, msg, 1) 1072 1073 #define UTEST_EXCEPTION_WITH_MESSAGE(x, exception_type, exception_message, \ 1074 msg, is_assert) \ 1075 UTEST_SURPRESS_WARNING_BEGIN do { \ 1076 int exception_caught = 0; \ 1077 char *message_caught = UTEST_NULL; \ 1078 try { \ 1079 x; \ 1080 } catch (const exception_type &e) { \ 1081 const char *const what = e.what(); \ 1082 exception_caught = 1; \ 1083 if (0 != \ 1084 UTEST_STRNCMP(what, exception_message, strlen(exception_message))) { \ 1085 const size_t message_size = strlen(what) + 1; \ 1086 message_caught = UTEST_PTR_CAST(char *, malloc(message_size)); \ 1087 UTEST_STRNCPY(message_caught, what, message_size); \ 1088 } \ 1089 } catch (...) { \ 1090 exception_caught = 2; \ 1091 } \ 1092 if (1 != exception_caught) { \ 1093 UTEST_PRINTF("%s:%i: Failure\n", __FILE__, __LINE__); \ 1094 UTEST_PRINTF(" Expected : %s exception\n", #exception_type); \ 1095 UTEST_PRINTF(" Actual : %s\n", (2 == exception_caught) \ 1096 ? "Unexpected exception" \ 1097 : "No exception"); \ 1098 if (strlen(msg) > 0) { \ 1099 UTEST_PRINTF(" Message : %s\n", msg); \ 1100 } \ 1101 *utest_result = UTEST_TEST_FAILURE; \ 1102 if (is_assert) { \ 1103 return; \ 1104 } \ 1105 } else if (UTEST_NULL != message_caught) { \ 1106 UTEST_PRINTF("%s:%i: Failure\n", __FILE__, __LINE__); \ 1107 UTEST_PRINTF(" Expected : %s exception with message %s\n", \ 1108 #exception_type, exception_message); \ 1109 UTEST_PRINTF(" Actual message : %s\n", message_caught); \ 1110 if (strlen(msg) > 0) { \ 1111 UTEST_PRINTF(" Message : %s\n", msg); \ 1112 } \ 1113 *utest_result = UTEST_TEST_FAILURE; \ 1114 free(message_caught); \ 1115 if (is_assert) { \ 1116 return; \ 1117 } \ 1118 } \ 1119 } \ 1120 while (0) \ 1121 UTEST_SURPRESS_WARNING_END 1122 1123 #define EXPECT_EXCEPTION_WITH_MESSAGE(x, exception_type, exception_message) \ 1124 UTEST_EXCEPTION_WITH_MESSAGE(x, exception_type, exception_message, "", 0) 1125 #define EXPECT_EXCEPTION_WITH_MESSAGE_MSG(x, exception_type, \ 1126 exception_message, msg) \ 1127 UTEST_EXCEPTION_WITH_MESSAGE(x, exception_type, exception_message, msg, 0) 1128 #define ASSERT_EXCEPTION_WITH_MESSAGE(x, exception_type, exception_message) \ 1129 UTEST_EXCEPTION_WITH_MESSAGE(x, exception_type, exception_message, "", 1) 1130 #define ASSERT_EXCEPTION_WITH_MESSAGE_MSG(x, exception_type, \ 1131 exception_message, msg) \ 1132 UTEST_EXCEPTION_WITH_MESSAGE(x, exception_type, exception_message, msg, 1) 1133 #endif 1134 1135 #if defined(__clang__) 1136 #if __has_warning("-Wunsafe-buffer-usage") 1137 #define UTEST_SURPRESS_WARNINGS_BEGIN \ 1138 _Pragma("clang diagnostic push") \ 1139 _Pragma("clang diagnostic ignored \"-Wunsafe-buffer-usage\"") 1140 #define UTEST_SURPRESS_WARNINGS_END _Pragma("clang diagnostic pop") 1141 #else 1142 #define UTEST_SURPRESS_WARNINGS_BEGIN 1143 #define UTEST_SURPRESS_WARNINGS_END 1144 #endif 1145 #elif defined(__GNUC__) && __GNUC__ >= 8 && defined(__cplusplus) 1146 #define UTEST_SURPRESS_WARNINGS_BEGIN \ 1147 _Pragma("GCC diagnostic push") \ 1148 _Pragma("GCC diagnostic ignored \"-Wclass-memaccess\"") 1149 #define UTEST_SURPRESS_WARNINGS_END _Pragma("GCC diagnostic pop") 1150 #else 1151 #define UTEST_SURPRESS_WARNINGS_BEGIN 1152 #define UTEST_SURPRESS_WARNINGS_END 1153 #endif 1154 1155 #define UTEST(SET, NAME) \ 1156 UTEST_SURPRESS_WARNINGS_BEGIN \ 1157 UTEST_EXTERN struct utest_state_s utest_state; \ 1158 static void utest_run_##SET##_##NAME(int *utest_result); \ 1159 static void utest_##SET##_##NAME(int *utest_result, size_t utest_index) { \ 1160 (void)utest_index; \ 1161 utest_run_##SET##_##NAME(utest_result); \ 1162 } \ 1163 UTEST_INITIALIZER(utest_register_##SET##_##NAME) { \ 1164 const size_t index = utest_state.tests_length++; \ 1165 const char name_part[] = #SET "." #NAME; \ 1166 const size_t name_size = strlen(name_part) + 1; \ 1167 char *name = UTEST_PTR_CAST(char *, malloc(name_size)); \ 1168 utest_state.tests = UTEST_PTR_CAST( \ 1169 struct utest_test_state_s *, \ 1170 utest_realloc(UTEST_PTR_CAST(void *, utest_state.tests), \ 1171 sizeof(struct utest_test_state_s) * \ 1172 utest_state.tests_length)); \ 1173 if (utest_state.tests && name) { \ 1174 utest_state.tests[index].func = &utest_##SET##_##NAME; \ 1175 utest_state.tests[index].name = name; \ 1176 utest_state.tests[index].index = 0; \ 1177 UTEST_SNPRINTF(name, name_size, "%s", name_part); \ 1178 } else { \ 1179 if (utest_state.tests) { \ 1180 free(utest_state.tests); \ 1181 utest_state.tests = NULL; \ 1182 } \ 1183 if (name) { \ 1184 free(name); \ 1185 } \ 1186 } \ 1187 } \ 1188 UTEST_SURPRESS_WARNINGS_END \ 1189 void utest_run_##SET##_##NAME(int *utest_result) 1190 1191 #define UTEST_F_SETUP(FIXTURE) \ 1192 static void utest_f_setup_##FIXTURE(int *utest_result, \ 1193 struct FIXTURE *utest_fixture) 1194 1195 #define UTEST_F_TEARDOWN(FIXTURE) \ 1196 static void utest_f_teardown_##FIXTURE(int *utest_result, \ 1197 struct FIXTURE *utest_fixture) 1198 1199 #define UTEST_F(FIXTURE, NAME) \ 1200 UTEST_SURPRESS_WARNINGS_BEGIN \ 1201 UTEST_EXTERN struct utest_state_s utest_state; \ 1202 static void utest_f_setup_##FIXTURE(int *, struct FIXTURE *); \ 1203 static void utest_f_teardown_##FIXTURE(int *, struct FIXTURE *); \ 1204 static void utest_run_##FIXTURE##_##NAME(int *, struct FIXTURE *); \ 1205 static void utest_f_##FIXTURE##_##NAME(int *utest_result, \ 1206 size_t utest_index) { \ 1207 struct FIXTURE fixture; \ 1208 (void)utest_index; \ 1209 memset(&fixture, 0, sizeof(fixture)); \ 1210 utest_f_setup_##FIXTURE(utest_result, &fixture); \ 1211 if (UTEST_TEST_PASSED != *utest_result) { \ 1212 return; \ 1213 } \ 1214 utest_run_##FIXTURE##_##NAME(utest_result, &fixture); \ 1215 utest_f_teardown_##FIXTURE(utest_result, &fixture); \ 1216 } \ 1217 UTEST_INITIALIZER(utest_register_##FIXTURE##_##NAME) { \ 1218 const size_t index = utest_state.tests_length++; \ 1219 const char name_part[] = #FIXTURE "." #NAME; \ 1220 const size_t name_size = strlen(name_part) + 1; \ 1221 char *name = UTEST_PTR_CAST(char *, malloc(name_size)); \ 1222 utest_state.tests = UTEST_PTR_CAST( \ 1223 struct utest_test_state_s *, \ 1224 utest_realloc(UTEST_PTR_CAST(void *, utest_state.tests), \ 1225 sizeof(struct utest_test_state_s) * \ 1226 utest_state.tests_length)); \ 1227 if (utest_state.tests && name) { \ 1228 utest_state.tests[index].func = &utest_f_##FIXTURE##_##NAME; \ 1229 utest_state.tests[index].name = name; \ 1230 utest_state.tests[index].index = 0; \ 1231 UTEST_SNPRINTF(name, name_size, "%s", name_part); \ 1232 } else { \ 1233 if (utest_state.tests) { \ 1234 free(utest_state.tests); \ 1235 utest_state.tests = NULL; \ 1236 } \ 1237 if (name) { \ 1238 free(name); \ 1239 } \ 1240 } \ 1241 } \ 1242 UTEST_SURPRESS_WARNINGS_END \ 1243 void utest_run_##FIXTURE##_##NAME(int *utest_result, \ 1244 struct FIXTURE *utest_fixture) 1245 1246 #define UTEST_I_SETUP(FIXTURE) \ 1247 static void utest_i_setup_##FIXTURE( \ 1248 int *utest_result, struct FIXTURE *utest_fixture, size_t utest_index) 1249 1250 #define UTEST_I_TEARDOWN(FIXTURE) \ 1251 static void utest_i_teardown_##FIXTURE( \ 1252 int *utest_result, struct FIXTURE *utest_fixture, size_t utest_index) 1253 1254 #define UTEST_I(FIXTURE, NAME, INDEX) \ 1255 UTEST_SURPRESS_WARNINGS_BEGIN \ 1256 UTEST_EXTERN struct utest_state_s utest_state; \ 1257 static void utest_run_##FIXTURE##_##NAME##_##INDEX(int *, struct FIXTURE *); \ 1258 static void utest_i_##FIXTURE##_##NAME##_##INDEX(int *utest_result, \ 1259 size_t index) { \ 1260 struct FIXTURE fixture; \ 1261 memset(&fixture, 0, sizeof(fixture)); \ 1262 utest_i_setup_##FIXTURE(utest_result, &fixture, index); \ 1263 if (UTEST_TEST_PASSED != *utest_result) { \ 1264 return; \ 1265 } \ 1266 utest_run_##FIXTURE##_##NAME##_##INDEX(utest_result, &fixture); \ 1267 utest_i_teardown_##FIXTURE(utest_result, &fixture, index); \ 1268 } \ 1269 UTEST_INITIALIZER(utest_register_##FIXTURE##_##NAME##_##INDEX) { \ 1270 size_t i; \ 1271 utest_uint64_t iUp; \ 1272 for (i = 0; i < (INDEX); i++) { \ 1273 const size_t index = utest_state.tests_length++; \ 1274 const char name_part[] = #FIXTURE "." #NAME; \ 1275 const size_t name_size = strlen(name_part) + 32; \ 1276 char *name = UTEST_PTR_CAST(char *, malloc(name_size)); \ 1277 utest_state.tests = UTEST_PTR_CAST( \ 1278 struct utest_test_state_s *, \ 1279 utest_realloc(UTEST_PTR_CAST(void *, utest_state.tests), \ 1280 sizeof(struct utest_test_state_s) * \ 1281 utest_state.tests_length)); \ 1282 if (utest_state.tests && name) { \ 1283 utest_state.tests[index].func = &utest_i_##FIXTURE##_##NAME##_##INDEX; \ 1284 utest_state.tests[index].index = i; \ 1285 utest_state.tests[index].name = name; \ 1286 iUp = UTEST_CAST(utest_uint64_t, i); \ 1287 UTEST_SNPRINTF(name, name_size, "%s/%" UTEST_PRIu64, name_part, iUp); \ 1288 } else { \ 1289 if (utest_state.tests) { \ 1290 free(utest_state.tests); \ 1291 utest_state.tests = NULL; \ 1292 } \ 1293 if (name) { \ 1294 free(name); \ 1295 } \ 1296 } \ 1297 } \ 1298 } \ 1299 UTEST_SURPRESS_WARNINGS_END \ 1300 void utest_run_##FIXTURE##_##NAME##_##INDEX(int *utest_result, \ 1301 struct FIXTURE *utest_fixture) 1302 1303 #ifdef __clang__ 1304 #pragma clang diagnostic push 1305 #pragma clang diagnostic ignored "-Wc++98-compat-pedantic" 1306 #endif 1307 1308 UTEST_WEAK 1309 double utest_fabs(double d); 1310 UTEST_WEAK 1311 double utest_fabs(double d) { 1312 union { 1313 double d; 1314 utest_uint64_t u; 1315 } both; 1316 both.d = d; 1317 both.u &= 0x7fffffffffffffffu; 1318 return both.d; 1319 } 1320 1321 UTEST_WEAK 1322 int utest_isnan(double d); 1323 UTEST_WEAK 1324 int utest_isnan(double d) { 1325 union { 1326 double d; 1327 utest_uint64_t u; 1328 } both; 1329 both.d = d; 1330 both.u &= 0x7fffffffffffffffu; 1331 return both.u > 0x7ff0000000000000u; 1332 } 1333 1334 #ifdef __clang__ 1335 #pragma clang diagnostic pop 1336 #endif 1337 1338 #if defined(__clang__) 1339 #if __has_warning("-Wunsafe-buffer-usage") 1340 #pragma clang diagnostic push 1341 #pragma clang diagnostic ignored "-Wunsafe-buffer-usage" 1342 #endif 1343 #endif 1344 1345 UTEST_WEAK 1346 int utest_should_filter_test(const char *filter, const char *testcase); 1347 UTEST_WEAK int utest_should_filter_test(const char *filter, 1348 const char *testcase) { 1349 if (filter) { 1350 const char *filter_cur = filter; 1351 const char *testcase_cur = testcase; 1352 const char *filter_wildcard = UTEST_NULL; 1353 1354 while (('\0' != *filter_cur) && ('\0' != *testcase_cur)) { 1355 if ('*' == *filter_cur) { 1356 /* store the position of the wildcard */ 1357 filter_wildcard = filter_cur; 1358 1359 /* skip the wildcard character */ 1360 filter_cur++; 1361 1362 while (('\0' != *filter_cur) && ('\0' != *testcase_cur)) { 1363 if ('*' == *filter_cur) { 1364 /* 1365 we found another wildcard (filter is something like *foo*) so we 1366 exit the current loop, and return to the parent loop to handle 1367 the wildcard case 1368 */ 1369 break; 1370 } else if (*filter_cur != *testcase_cur) { 1371 /* otherwise our filter didn't match, so reset it */ 1372 filter_cur = filter_wildcard; 1373 } 1374 1375 /* move testcase along */ 1376 testcase_cur++; 1377 1378 /* move filter along */ 1379 filter_cur++; 1380 } 1381 1382 if (('\0' == *filter_cur) && ('\0' == *testcase_cur)) { 1383 return 0; 1384 } 1385 1386 /* if the testcase has been exhausted, we don't have a match! */ 1387 if ('\0' == *testcase_cur) { 1388 return 1; 1389 } 1390 } else { 1391 if (*testcase_cur != *filter_cur) { 1392 /* test case doesn't match filter */ 1393 return 1; 1394 } else { 1395 /* move our filter and testcase forward */ 1396 testcase_cur++; 1397 filter_cur++; 1398 } 1399 } 1400 } 1401 1402 if (('\0' != *filter_cur) || 1403 (('\0' != *testcase_cur) && 1404 ((filter == filter_cur) || ('*' != filter_cur[-1])))) { 1405 /* we have a mismatch! */ 1406 return 1; 1407 } 1408 } 1409 1410 return 0; 1411 } 1412 1413 static UTEST_INLINE FILE *utest_fopen(const char *filename, const char *mode) { 1414 #ifdef _MSC_VER 1415 FILE *file; 1416 if (0 == fopen_s(&file, filename, mode)) { 1417 return file; 1418 } else { 1419 return UTEST_NULL; 1420 } 1421 #else 1422 return fopen(filename, mode); 1423 #endif 1424 } 1425 1426 static UTEST_INLINE int utest_main(int argc, const char *const argv[]); 1427 int utest_main(int argc, const char *const argv[]) { 1428 utest_uint64_t failed = 0; 1429 utest_uint64_t skipped = 0; 1430 size_t index = 0; 1431 size_t *failed_testcases = UTEST_NULL; 1432 size_t failed_testcases_length = 0; 1433 size_t *skipped_testcases = UTEST_NULL; 1434 size_t skipped_testcases_length = 0; 1435 const char *filter = UTEST_NULL; 1436 utest_uint64_t ran_tests = 0; 1437 int enable_mixed_units = 0; 1438 int random_order = 0; 1439 utest_uint32_t seed = 0; 1440 1441 enum colours { RESET, GREEN, RED, YELLOW }; 1442 1443 const int use_colours = UTEST_COLOUR_OUTPUT(); 1444 const char *colours[] = {"\033[0m", "\033[32m", "\033[31m", "\033[33m"}; 1445 1446 if (!use_colours) { 1447 for (index = 0; index < sizeof colours / sizeof colours[0]; index++) { 1448 colours[index] = ""; 1449 } 1450 } 1451 /* loop through all arguments looking for our options */ 1452 for (index = 1; index < UTEST_CAST(size_t, argc); index++) { 1453 /* Informational switches */ 1454 const char help_str[] = "--help"; 1455 const char list_str[] = "--list-tests"; 1456 /* Test config switches */ 1457 const char filter_str[] = "--filter="; 1458 const char output_str[] = "--output="; 1459 const char enable_mixed_units_str[] = "--enable-mixed-units"; 1460 const char random_order_str[] = "--random-order"; 1461 const char random_order_with_seed_str[] = "--random-order="; 1462 1463 if (0 == UTEST_STRNCMP(argv[index], help_str, strlen(help_str))) { 1464 printf("utest.h - the single file unit testing solution for C/C++!\n" 1465 "Command line Options:\n" 1466 " --help Show this message and exit.\n" 1467 " --filter=<filter> Filter the test cases to run (EG. " 1468 "MyTest*.a would run MyTestCase.a but not MyTestCase.b).\n" 1469 " --list-tests List testnames, one per line. Output " 1470 "names can be passed to --filter.\n"); 1471 printf(" --output=<output> Output an xunit XML file to the file " 1472 "specified in <output>.\n" 1473 " --enable-mixed-units Enable the per-test output to contain " 1474 "mixed units (s/ms/us/ns).\n" 1475 " --random-order[=<seed>] Randomize the order that the tests are " 1476 "ran in. If the optional <seed> argument is not provided, then a " 1477 "random starting seed is used.\n"); 1478 goto cleanup; 1479 } else if (0 == 1480 UTEST_STRNCMP(argv[index], filter_str, strlen(filter_str))) { 1481 /* user wants to filter what test cases run! */ 1482 filter = argv[index] + strlen(filter_str); 1483 } else if (0 == 1484 UTEST_STRNCMP(argv[index], output_str, strlen(output_str))) { 1485 utest_state.output = utest_fopen(argv[index] + strlen(output_str), "w+"); 1486 } else if (0 == UTEST_STRNCMP(argv[index], list_str, strlen(list_str))) { 1487 for (index = 0; index < utest_state.tests_length; index++) { 1488 UTEST_PRINTF("%s\n", utest_state.tests[index].name); 1489 } 1490 /* when printing the test list, don't actually run the tests */ 1491 return 0; 1492 } else if (0 == UTEST_STRNCMP(argv[index], enable_mixed_units_str, 1493 strlen(enable_mixed_units_str))) { 1494 enable_mixed_units = 1; 1495 } else if (0 == UTEST_STRNCMP(argv[index], random_order_with_seed_str, 1496 strlen(random_order_with_seed_str))) { 1497 seed = 1498 UTEST_CAST(utest_uint32_t, 1499 strtoul(argv[index] + strlen(random_order_with_seed_str), 1500 UTEST_NULL, 10)); 1501 random_order = 1; 1502 } else if (0 == UTEST_STRNCMP(argv[index], random_order_str, 1503 strlen(random_order_str))) { 1504 const utest_int64_t ns = utest_ns(); 1505 1506 // Some really poor pseudo-random using the current time. I do this 1507 // because I really want to avoid using C's rand() because that'd mean our 1508 // random would be affected by any srand() usage by the user (which I 1509 // don't want). 1510 seed = UTEST_CAST(utest_uint32_t, ns >> 32) * 31 + 1511 UTEST_CAST(utest_uint32_t, ns & 0xffffffff); 1512 random_order = 1; 1513 } 1514 } 1515 1516 if (random_order) { 1517 // Use Fisher-Yates with the Durstenfield's version to randomly re-order the 1518 // tests. 1519 for (index = utest_state.tests_length; index > 1; index--) { 1520 // For the random order we'll use PCG. 1521 const utest_uint32_t state = seed; 1522 const utest_uint32_t word = 1523 ((state >> ((state >> 28u) + 4u)) ^ state) * 277803737u; 1524 const utest_uint32_t next = 1525 ((word >> 22u) ^ word) % UTEST_CAST(utest_uint32_t, index); 1526 1527 // Swap the randomly chosen element into the last location. 1528 const struct utest_test_state_s copy = utest_state.tests[index - 1]; 1529 utest_state.tests[index - 1] = utest_state.tests[next]; 1530 utest_state.tests[next] = copy; 1531 1532 // Move the seed onwards. 1533 seed = seed * 747796405u + 2891336453u; 1534 } 1535 } 1536 1537 for (index = 0; index < utest_state.tests_length; index++) { 1538 if (utest_should_filter_test(filter, utest_state.tests[index].name)) { 1539 continue; 1540 } 1541 1542 ran_tests++; 1543 } 1544 1545 printf("%s[==========]%s Running %" UTEST_PRIu64 " test cases.\n", 1546 colours[GREEN], colours[RESET], UTEST_CAST(utest_uint64_t, ran_tests)); 1547 1548 if (utest_state.output) { 1549 fprintf(utest_state.output, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"); 1550 fprintf(utest_state.output, 1551 "<testsuites tests=\"%" UTEST_PRIu64 "\" name=\"All\">\n", 1552 UTEST_CAST(utest_uint64_t, ran_tests)); 1553 fprintf(utest_state.output, 1554 "<testsuite name=\"Tests\" tests=\"%" UTEST_PRIu64 "\">\n", 1555 UTEST_CAST(utest_uint64_t, ran_tests)); 1556 } 1557 1558 for (index = 0; index < utest_state.tests_length; index++) { 1559 int result = UTEST_TEST_PASSED; 1560 utest_int64_t ns = 0; 1561 1562 if (utest_should_filter_test(filter, utest_state.tests[index].name)) { 1563 continue; 1564 } 1565 1566 printf("%s[ RUN ]%s %s\n", colours[GREEN], colours[RESET], 1567 utest_state.tests[index].name); 1568 1569 if (utest_state.output) { 1570 fprintf(utest_state.output, "<testcase name=\"%s\">", 1571 utest_state.tests[index].name); 1572 } 1573 1574 ns = utest_ns(); 1575 errno = 0; 1576 #if defined(UTEST_HAS_EXCEPTIONS) 1577 UTEST_SURPRESS_WARNING_BEGIN 1578 try { 1579 utest_state.tests[index].func(&result, utest_state.tests[index].index); 1580 } catch (const std::exception &err) { 1581 printf(" Exception : %s\n", err.what()); 1582 result = UTEST_TEST_FAILURE; 1583 } catch (...) { 1584 printf(" Exception : Unknown\n"); 1585 result = UTEST_TEST_FAILURE; 1586 } 1587 UTEST_SURPRESS_WARNING_END 1588 #else 1589 utest_state.tests[index].func(&result, utest_state.tests[index].index); 1590 #endif 1591 ns = utest_ns() - ns; 1592 1593 if (utest_state.output) { 1594 fprintf(utest_state.output, "</testcase>\n"); 1595 } 1596 1597 // Record the failing test. 1598 if (UTEST_TEST_FAILURE == result) { 1599 const size_t failed_testcase_index = failed_testcases_length++; 1600 failed_testcases = UTEST_PTR_CAST( 1601 size_t *, utest_realloc(UTEST_PTR_CAST(void *, failed_testcases), 1602 sizeof(size_t) * failed_testcases_length)); 1603 if (UTEST_NULL != failed_testcases) { 1604 failed_testcases[failed_testcase_index] = index; 1605 } 1606 failed++; 1607 } else if (UTEST_TEST_SKIPPED == result) { 1608 const size_t skipped_testcase_index = skipped_testcases_length++; 1609 skipped_testcases = UTEST_PTR_CAST( 1610 size_t *, utest_realloc(UTEST_PTR_CAST(void *, skipped_testcases), 1611 sizeof(size_t) * skipped_testcases_length)); 1612 if (UTEST_NULL != skipped_testcases) { 1613 skipped_testcases[skipped_testcase_index] = index; 1614 } 1615 skipped++; 1616 } 1617 1618 { 1619 const char *const units[] = {"ns", "us", "ms", "s", UTEST_NULL}; 1620 unsigned int unit_index = 0; 1621 utest_int64_t time = ns; 1622 1623 if (enable_mixed_units) { 1624 for (unit_index = 0; UTEST_NULL != units[unit_index]; unit_index++) { 1625 if (10000 > time) { 1626 break; 1627 } 1628 1629 time /= 1000; 1630 } 1631 } 1632 1633 if (UTEST_TEST_FAILURE == result) { 1634 printf("%s[ FAILED ]%s %s (%" UTEST_PRId64 "%s)\n", colours[RED], 1635 colours[RESET], utest_state.tests[index].name, time, 1636 units[unit_index]); 1637 } else if (UTEST_TEST_SKIPPED == result) { 1638 printf("%s[ SKIPPED ]%s %s (%" UTEST_PRId64 "%s)\n", colours[YELLOW], 1639 colours[RESET], utest_state.tests[index].name, time, 1640 units[unit_index]); 1641 } else { 1642 printf("%s[ OK ]%s %s (%" UTEST_PRId64 "%s)\n", colours[GREEN], 1643 colours[RESET], utest_state.tests[index].name, time, 1644 units[unit_index]); 1645 } 1646 } 1647 } 1648 1649 printf("%s[==========]%s %" UTEST_PRIu64 " test cases ran.\n", colours[GREEN], 1650 colours[RESET], ran_tests); 1651 printf("%s[ PASSED ]%s %" UTEST_PRIu64 " tests.\n", colours[GREEN], 1652 colours[RESET], ran_tests - failed - skipped); 1653 1654 if (0 != skipped) { 1655 printf("%s[ SKIPPED ]%s %" UTEST_PRIu64 " tests, listed below:\n", 1656 colours[YELLOW], colours[RESET], skipped); 1657 for (index = 0; index < skipped_testcases_length; index++) { 1658 printf("%s[ SKIPPED ]%s %s\n", colours[YELLOW], colours[RESET], 1659 utest_state.tests[skipped_testcases[index]].name); 1660 } 1661 } 1662 1663 if (0 != failed) { 1664 printf("%s[ FAILED ]%s %" UTEST_PRIu64 " tests, listed below:\n", 1665 colours[RED], colours[RESET], failed); 1666 for (index = 0; index < failed_testcases_length; index++) { 1667 printf("%s[ FAILED ]%s %s\n", colours[RED], colours[RESET], 1668 utest_state.tests[failed_testcases[index]].name); 1669 } 1670 } 1671 1672 if (utest_state.output) { 1673 fprintf(utest_state.output, "</testsuite>\n</testsuites>\n"); 1674 } 1675 1676 cleanup: 1677 for (index = 0; index < utest_state.tests_length; index++) { 1678 free(UTEST_PTR_CAST(void *, utest_state.tests[index].name)); 1679 } 1680 1681 free(UTEST_PTR_CAST(void *, skipped_testcases)); 1682 free(UTEST_PTR_CAST(void *, failed_testcases)); 1683 free(UTEST_PTR_CAST(void *, utest_state.tests)); 1684 1685 if (utest_state.output) { 1686 fclose(utest_state.output); 1687 } 1688 1689 return UTEST_CAST(int, failed); 1690 } 1691 1692 #if defined(__clang__) 1693 #if __has_warning("-Wunsafe-buffer-usage") 1694 #pragma clang diagnostic pop 1695 #endif 1696 #endif 1697 1698 /* 1699 we need, in exactly one source file, define the global struct that will hold 1700 the data we need to run utest. This macro allows the user to declare the 1701 data without having to use the UTEST_MAIN macro, thus allowing them to write 1702 their own main() function. 1703 */ 1704 #define UTEST_STATE() struct utest_state_s utest_state = {0, 0, 0} 1705 1706 /* 1707 define a main() function to call into utest.h and start executing tests! A 1708 user can optionally not use this macro, and instead define their own main() 1709 function and manually call utest_main. The user must, in exactly one source 1710 file, use the UTEST_STATE macro to declare a global struct variable that 1711 utest requires. 1712 */ 1713 #define UTEST_MAIN() \ 1714 UTEST_STATE(); \ 1715 int main(int argc, const char *const argv[]) { \ 1716 return utest_main(argc, argv); \ 1717 } 1718 1719 #endif /* SHEREDOM_UTEST_H_INCLUDED */