minimap2 0.2.24.3 → 0.2.24.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (101) hide show
  1. checksums.yaml +4 -4
  2. data/ext/minimap2/lib/simde/CONTRIBUTING.md +114 -0
  3. data/ext/minimap2/lib/simde/COPYING +20 -0
  4. data/ext/minimap2/lib/simde/README.md +333 -0
  5. data/ext/minimap2/lib/simde/amalgamate.py +58 -0
  6. data/ext/minimap2/lib/simde/meson.build +33 -0
  7. data/ext/minimap2/lib/simde/netlify.toml +20 -0
  8. data/ext/minimap2/lib/simde/simde/arm/neon/float32x2.h +140 -0
  9. data/ext/minimap2/lib/simde/simde/arm/neon/float32x4.h +137 -0
  10. data/ext/minimap2/lib/simde/simde/arm/neon/float64x1.h +142 -0
  11. data/ext/minimap2/lib/simde/simde/arm/neon/float64x2.h +145 -0
  12. data/ext/minimap2/lib/simde/simde/arm/neon/int16x4.h +140 -0
  13. data/ext/minimap2/lib/simde/simde/arm/neon/int16x8.h +145 -0
  14. data/ext/minimap2/lib/simde/simde/arm/neon/int32x2.h +140 -0
  15. data/ext/minimap2/lib/simde/simde/arm/neon/int32x4.h +143 -0
  16. data/ext/minimap2/lib/simde/simde/arm/neon/int64x1.h +137 -0
  17. data/ext/minimap2/lib/simde/simde/arm/neon/int64x2.h +141 -0
  18. data/ext/minimap2/lib/simde/simde/arm/neon/int8x16.h +147 -0
  19. data/ext/minimap2/lib/simde/simde/arm/neon/int8x8.h +141 -0
  20. data/ext/minimap2/lib/simde/simde/arm/neon/uint16x4.h +134 -0
  21. data/ext/minimap2/lib/simde/simde/arm/neon/uint16x8.h +138 -0
  22. data/ext/minimap2/lib/simde/simde/arm/neon/uint32x2.h +134 -0
  23. data/ext/minimap2/lib/simde/simde/arm/neon/uint32x4.h +137 -0
  24. data/ext/minimap2/lib/simde/simde/arm/neon/uint64x1.h +131 -0
  25. data/ext/minimap2/lib/simde/simde/arm/neon/uint64x2.h +135 -0
  26. data/ext/minimap2/lib/simde/simde/arm/neon/uint8x16.h +141 -0
  27. data/ext/minimap2/lib/simde/simde/arm/neon/uint8x8.h +135 -0
  28. data/ext/minimap2/lib/simde/simde/arm/neon.h +97 -0
  29. data/ext/minimap2/lib/simde/simde/check.h +267 -0
  30. data/ext/minimap2/lib/simde/simde/debug-trap.h +83 -0
  31. data/ext/minimap2/lib/simde/simde/hedley.h +1899 -0
  32. data/ext/minimap2/lib/simde/simde/simde-arch.h +445 -0
  33. data/ext/minimap2/lib/simde/simde/simde-common.h +697 -0
  34. data/ext/minimap2/lib/simde/simde/x86/avx.h +5385 -0
  35. data/ext/minimap2/lib/simde/simde/x86/avx2.h +2402 -0
  36. data/ext/minimap2/lib/simde/simde/x86/avx512bw.h +391 -0
  37. data/ext/minimap2/lib/simde/simde/x86/avx512f.h +3389 -0
  38. data/ext/minimap2/lib/simde/simde/x86/avx512vl.h +112 -0
  39. data/ext/minimap2/lib/simde/simde/x86/fma.h +659 -0
  40. data/ext/minimap2/lib/simde/simde/x86/mmx.h +2210 -0
  41. data/ext/minimap2/lib/simde/simde/x86/sse.h +3696 -0
  42. data/ext/minimap2/lib/simde/simde/x86/sse2.h +5991 -0
  43. data/ext/minimap2/lib/simde/simde/x86/sse3.h +343 -0
  44. data/ext/minimap2/lib/simde/simde/x86/sse4.1.h +1783 -0
  45. data/ext/minimap2/lib/simde/simde/x86/sse4.2.h +105 -0
  46. data/ext/minimap2/lib/simde/simde/x86/ssse3.h +1053 -0
  47. data/ext/minimap2/lib/simde/simde/x86/svml.h +543 -0
  48. data/ext/minimap2/lib/simde/test/CMakeLists.txt +166 -0
  49. data/ext/minimap2/lib/simde/test/arm/meson.build +4 -0
  50. data/ext/minimap2/lib/simde/test/arm/neon/meson.build +23 -0
  51. data/ext/minimap2/lib/simde/test/arm/neon/skel.c +871 -0
  52. data/ext/minimap2/lib/simde/test/arm/neon/test-neon-internal.h +134 -0
  53. data/ext/minimap2/lib/simde/test/arm/neon/test-neon.c +39 -0
  54. data/ext/minimap2/lib/simde/test/arm/neon/test-neon.h +10 -0
  55. data/ext/minimap2/lib/simde/test/arm/neon/vadd.c +1260 -0
  56. data/ext/minimap2/lib/simde/test/arm/neon/vdup_n.c +873 -0
  57. data/ext/minimap2/lib/simde/test/arm/neon/vmul.c +1084 -0
  58. data/ext/minimap2/lib/simde/test/arm/neon/vsub.c +1260 -0
  59. data/ext/minimap2/lib/simde/test/arm/test-arm-internal.h +18 -0
  60. data/ext/minimap2/lib/simde/test/arm/test-arm.c +20 -0
  61. data/ext/minimap2/lib/simde/test/arm/test-arm.h +8 -0
  62. data/ext/minimap2/lib/simde/test/cmake/AddCompilerFlags.cmake +171 -0
  63. data/ext/minimap2/lib/simde/test/cmake/ExtraWarningFlags.cmake +68 -0
  64. data/ext/minimap2/lib/simde/test/meson.build +64 -0
  65. data/ext/minimap2/lib/simde/test/munit/COPYING +21 -0
  66. data/ext/minimap2/lib/simde/test/munit/Makefile +55 -0
  67. data/ext/minimap2/lib/simde/test/munit/README.md +54 -0
  68. data/ext/minimap2/lib/simde/test/munit/example.c +351 -0
  69. data/ext/minimap2/lib/simde/test/munit/meson.build +37 -0
  70. data/ext/minimap2/lib/simde/test/munit/munit.c +2055 -0
  71. data/ext/minimap2/lib/simde/test/munit/munit.h +535 -0
  72. data/ext/minimap2/lib/simde/test/run-tests.c +20 -0
  73. data/ext/minimap2/lib/simde/test/run-tests.h +260 -0
  74. data/ext/minimap2/lib/simde/test/x86/avx.c +13752 -0
  75. data/ext/minimap2/lib/simde/test/x86/avx2.c +9977 -0
  76. data/ext/minimap2/lib/simde/test/x86/avx512bw.c +2664 -0
  77. data/ext/minimap2/lib/simde/test/x86/avx512f.c +10416 -0
  78. data/ext/minimap2/lib/simde/test/x86/avx512vl.c +210 -0
  79. data/ext/minimap2/lib/simde/test/x86/fma.c +2557 -0
  80. data/ext/minimap2/lib/simde/test/x86/meson.build +33 -0
  81. data/ext/minimap2/lib/simde/test/x86/mmx.c +2878 -0
  82. data/ext/minimap2/lib/simde/test/x86/skel.c +2984 -0
  83. data/ext/minimap2/lib/simde/test/x86/sse.c +5121 -0
  84. data/ext/minimap2/lib/simde/test/x86/sse2.c +9860 -0
  85. data/ext/minimap2/lib/simde/test/x86/sse3.c +486 -0
  86. data/ext/minimap2/lib/simde/test/x86/sse4.1.c +3446 -0
  87. data/ext/minimap2/lib/simde/test/x86/sse4.2.c +101 -0
  88. data/ext/minimap2/lib/simde/test/x86/ssse3.c +2084 -0
  89. data/ext/minimap2/lib/simde/test/x86/svml.c +1545 -0
  90. data/ext/minimap2/lib/simde/test/x86/test-avx.h +16 -0
  91. data/ext/minimap2/lib/simde/test/x86/test-avx512.h +25 -0
  92. data/ext/minimap2/lib/simde/test/x86/test-mmx.h +13 -0
  93. data/ext/minimap2/lib/simde/test/x86/test-sse.h +13 -0
  94. data/ext/minimap2/lib/simde/test/x86/test-sse2.h +13 -0
  95. data/ext/minimap2/lib/simde/test/x86/test-x86-internal.h +196 -0
  96. data/ext/minimap2/lib/simde/test/x86/test-x86.c +48 -0
  97. data/ext/minimap2/lib/simde/test/x86/test-x86.h +8 -0
  98. data/lib/minimap2/aligner.rb +2 -2
  99. data/lib/minimap2/ffi/constants.rb +3 -0
  100. data/lib/minimap2/version.rb +1 -1
  101. metadata +99 -3
@@ -0,0 +1,2055 @@
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 paramter to an array of parameters. */
1076
+ static MunitResult
1077
+ munit_parameters_add(size_t* params_size, MunitParameter* params[MUNIT_ARRAY_PARAM(*params_size)], char* name, char* value) {
1078
+ *params = realloc(*params, sizeof(MunitParameter) * (*params_size + 2));
1079
+ if (*params == NULL)
1080
+ return MUNIT_ERROR;
1081
+
1082
+ (*params)[*params_size].name = name;
1083
+ (*params)[*params_size].value = value;
1084
+ (*params_size)++;
1085
+ (*params)[*params_size].name = NULL;
1086
+ (*params)[*params_size].value = NULL;
1087
+
1088
+ return MUNIT_OK;
1089
+ }
1090
+
1091
+ /* Concatenate two strings, but just return one of the components
1092
+ * unaltered if the other is NULL or "". */
1093
+ static char*
1094
+ munit_maybe_concat(size_t* len, char* prefix, char* suffix) {
1095
+ char* res;
1096
+ size_t res_l;
1097
+ const size_t prefix_l = prefix != NULL ? strlen(prefix) : 0;
1098
+ const size_t suffix_l = suffix != NULL ? strlen(suffix) : 0;
1099
+ if (prefix_l == 0 && suffix_l == 0) {
1100
+ res = NULL;
1101
+ res_l = 0;
1102
+ } else if (prefix_l == 0 && suffix_l != 0) {
1103
+ res = suffix;
1104
+ res_l = suffix_l;
1105
+ } else if (prefix_l != 0 && suffix_l == 0) {
1106
+ res = prefix;
1107
+ res_l = prefix_l;
1108
+ } else {
1109
+ res_l = prefix_l + suffix_l;
1110
+ res = malloc(res_l + 1);
1111
+ memcpy(res, prefix, prefix_l);
1112
+ memcpy(res + prefix_l, suffix, suffix_l);
1113
+ res[res_l] = 0;
1114
+ }
1115
+
1116
+ if (len != NULL)
1117
+ *len = res_l;
1118
+
1119
+ return res;
1120
+ }
1121
+
1122
+ /* Possbily free a string returned by munit_maybe_concat. */
1123
+ static void
1124
+ munit_maybe_free_concat(char* s, const char* prefix, const char* suffix) {
1125
+ if (prefix != s && suffix != s)
1126
+ free(s);
1127
+ }
1128
+
1129
+ /* Cheap string hash function, just used to salt the PRNG. */
1130
+ static munit_uint32_t
1131
+ munit_str_hash(const char* name) {
1132
+ const char *p;
1133
+ munit_uint32_t h = 5381U;
1134
+
1135
+ for (p = name; *p != '\0'; p++)
1136
+ h = (h << 5) + h + *p;
1137
+
1138
+ return h;
1139
+ }
1140
+
1141
+ static void
1142
+ munit_splice(int from, int to) {
1143
+ munit_uint8_t buf[1024];
1144
+ #if !defined(_WIN32)
1145
+ ssize_t len;
1146
+ ssize_t bytes_written;
1147
+ ssize_t write_res;
1148
+ #else
1149
+ int len;
1150
+ int bytes_written;
1151
+ int write_res;
1152
+ #endif
1153
+ do {
1154
+ len = read(from, buf, sizeof(buf));
1155
+ if (len > 0) {
1156
+ bytes_written = 0;
1157
+ do {
1158
+ write_res = write(to, buf + bytes_written, len - bytes_written);
1159
+ if (write_res < 0)
1160
+ break;
1161
+ bytes_written += write_res;
1162
+ } while (bytes_written < len);
1163
+ }
1164
+ else
1165
+ break;
1166
+ } while (1);
1167
+ }
1168
+
1169
+ /* This is the part that should be handled in the child process */
1170
+ static MunitResult
1171
+ munit_test_runner_exec(MunitTestRunner* runner, const MunitTest* test, const MunitParameter params[], MunitReport* report) {
1172
+ unsigned int iterations = runner->iterations;
1173
+ MunitResult result = MUNIT_FAIL;
1174
+ #if defined(MUNIT_ENABLE_TIMING)
1175
+ struct PsnipClockTimespec wall_clock_begin = { 0, }, wall_clock_end = { 0, };
1176
+ struct PsnipClockTimespec cpu_clock_begin = { 0, }, cpu_clock_end = { 0, };
1177
+ #endif
1178
+ unsigned int i = 0;
1179
+
1180
+ if ((test->options & MUNIT_TEST_OPTION_SINGLE_ITERATION) == MUNIT_TEST_OPTION_SINGLE_ITERATION)
1181
+ iterations = 1;
1182
+ else if (iterations == 0)
1183
+ iterations = runner->suite->iterations;
1184
+
1185
+ munit_rand_seed(runner->seed);
1186
+
1187
+ do {
1188
+ void* data = (test->setup == NULL) ? runner->user_data : test->setup(params, runner->user_data);
1189
+
1190
+ #if defined(MUNIT_ENABLE_TIMING)
1191
+ psnip_clock_get_time(PSNIP_CLOCK_TYPE_WALL, &wall_clock_begin);
1192
+ psnip_clock_get_time(PSNIP_CLOCK_TYPE_CPU, &cpu_clock_begin);
1193
+ #endif
1194
+
1195
+ result = test->test(params, data);
1196
+
1197
+ #if defined(MUNIT_ENABLE_TIMING)
1198
+ psnip_clock_get_time(PSNIP_CLOCK_TYPE_WALL, &wall_clock_end);
1199
+ psnip_clock_get_time(PSNIP_CLOCK_TYPE_CPU, &cpu_clock_end);
1200
+ #endif
1201
+
1202
+ if (test->tear_down != NULL)
1203
+ test->tear_down(data);
1204
+
1205
+ if (MUNIT_LIKELY(result == MUNIT_OK)) {
1206
+ report->successful++;
1207
+ #if defined(MUNIT_ENABLE_TIMING)
1208
+ report->wall_clock += munit_clock_get_elapsed(&wall_clock_begin, &wall_clock_end);
1209
+ report->cpu_clock += munit_clock_get_elapsed(&cpu_clock_begin, &cpu_clock_end);
1210
+ #endif
1211
+ } else {
1212
+ switch ((int) result) {
1213
+ case MUNIT_SKIP:
1214
+ report->skipped++;
1215
+ break;
1216
+ case MUNIT_FAIL:
1217
+ report->failed++;
1218
+ break;
1219
+ case MUNIT_ERROR:
1220
+ report->errored++;
1221
+ break;
1222
+ default:
1223
+ break;
1224
+ }
1225
+ break;
1226
+ }
1227
+ } while (++i < iterations);
1228
+
1229
+ return result;
1230
+ }
1231
+
1232
+ #if defined(MUNIT_EMOTICON)
1233
+ # define MUNIT_RESULT_STRING_OK ":)"
1234
+ # define MUNIT_RESULT_STRING_SKIP ":|"
1235
+ # define MUNIT_RESULT_STRING_FAIL ":("
1236
+ # define MUNIT_RESULT_STRING_ERROR ":o"
1237
+ # define MUNIT_RESULT_STRING_TODO ":/"
1238
+ #else
1239
+ # define MUNIT_RESULT_STRING_OK "OK "
1240
+ # define MUNIT_RESULT_STRING_SKIP "SKIP "
1241
+ # define MUNIT_RESULT_STRING_FAIL "FAIL "
1242
+ # define MUNIT_RESULT_STRING_ERROR "ERROR"
1243
+ # define MUNIT_RESULT_STRING_TODO "TODO "
1244
+ #endif
1245
+
1246
+ static void
1247
+ munit_test_runner_print_color(const MunitTestRunner* runner, const char* string, char color) {
1248
+ if (runner->colorize)
1249
+ fprintf(MUNIT_OUTPUT_FILE, "\x1b[3%cm%s\x1b[39m", color, string);
1250
+ else
1251
+ fputs(string, MUNIT_OUTPUT_FILE);
1252
+ }
1253
+
1254
+ #if !defined(MUNIT_NO_BUFFER)
1255
+ static int
1256
+ munit_replace_stderr(FILE* stderr_buf) {
1257
+ if (stderr_buf != NULL) {
1258
+ const int orig_stderr = dup(STDERR_FILENO);
1259
+
1260
+ int errfd = fileno(stderr_buf);
1261
+ if (MUNIT_UNLIKELY(errfd == -1)) {
1262
+ exit(EXIT_FAILURE);
1263
+ }
1264
+
1265
+ dup2(errfd, STDERR_FILENO);
1266
+
1267
+ return orig_stderr;
1268
+ }
1269
+
1270
+ return -1;
1271
+ }
1272
+
1273
+ static void
1274
+ munit_restore_stderr(int orig_stderr) {
1275
+ if (orig_stderr != -1) {
1276
+ dup2(orig_stderr, STDERR_FILENO);
1277
+ close(orig_stderr);
1278
+ }
1279
+ }
1280
+ #endif /* !defined(MUNIT_NO_BUFFER) */
1281
+
1282
+ /* Run a test with the specified parameters. */
1283
+ static void
1284
+ munit_test_runner_run_test_with_params(MunitTestRunner* runner, const MunitTest* test, const MunitParameter params[]) {
1285
+ MunitResult result = MUNIT_OK;
1286
+ MunitReport report = {
1287
+ 0, 0, 0, 0,
1288
+ #if defined(MUNIT_ENABLE_TIMING)
1289
+ 0, 0
1290
+ #endif
1291
+ };
1292
+ unsigned int output_l;
1293
+ munit_bool first;
1294
+ const MunitParameter* param;
1295
+ FILE* stderr_buf;
1296
+ #if !defined(MUNIT_NO_FORK)
1297
+ int pipefd[2];
1298
+ pid_t fork_pid;
1299
+ int orig_stderr;
1300
+ ssize_t bytes_written = 0;
1301
+ ssize_t write_res;
1302
+ ssize_t bytes_read = 0;
1303
+ ssize_t read_res;
1304
+ int status = 0;
1305
+ pid_t changed_pid;
1306
+ #endif
1307
+
1308
+ if (params != NULL) {
1309
+ output_l = 2;
1310
+ fputs(" ", MUNIT_OUTPUT_FILE);
1311
+ first = 1;
1312
+ for (param = params ; param != NULL && param->name != NULL ; param++) {
1313
+ if (!first) {
1314
+ fputs(", ", MUNIT_OUTPUT_FILE);
1315
+ output_l += 2;
1316
+ } else {
1317
+ first = 0;
1318
+ }
1319
+
1320
+ output_l += fprintf(MUNIT_OUTPUT_FILE, "%s=%s", param->name, param->value);
1321
+ }
1322
+ while (output_l++ < MUNIT_TEST_NAME_LEN) {
1323
+ fputc(' ', MUNIT_OUTPUT_FILE);
1324
+ }
1325
+ }
1326
+
1327
+ fflush(MUNIT_OUTPUT_FILE);
1328
+
1329
+ stderr_buf = NULL;
1330
+ #if !defined(_WIN32) || defined(__MINGW32__)
1331
+ stderr_buf = tmpfile();
1332
+ #else
1333
+ tmpfile_s(&stderr_buf);
1334
+ #endif
1335
+ if (stderr_buf == NULL) {
1336
+ munit_log_errno(MUNIT_LOG_ERROR, stderr, "unable to create buffer for stderr");
1337
+ result = MUNIT_ERROR;
1338
+ goto print_result;
1339
+ }
1340
+
1341
+ #if !defined(MUNIT_NO_FORK)
1342
+ if (runner->fork) {
1343
+ pipefd[0] = -1;
1344
+ pipefd[1] = -1;
1345
+ if (pipe(pipefd) != 0) {
1346
+ munit_log_errno(MUNIT_LOG_ERROR, stderr, "unable to create pipe");
1347
+ result = MUNIT_ERROR;
1348
+ goto print_result;
1349
+ }
1350
+
1351
+ fork_pid = fork();
1352
+ if (fork_pid == 0) {
1353
+ close(pipefd[0]);
1354
+
1355
+ orig_stderr = munit_replace_stderr(stderr_buf);
1356
+ munit_test_runner_exec(runner, test, params, &report);
1357
+
1358
+ /* Note that we don't restore stderr. This is so we can buffer
1359
+ * things written to stderr later on (such as by
1360
+ * asan/tsan/ubsan, valgrind, etc.) */
1361
+ close(orig_stderr);
1362
+
1363
+ do {
1364
+ write_res = write(pipefd[1], ((munit_uint8_t*) (&report)) + bytes_written, sizeof(report) - bytes_written);
1365
+ if (write_res < 0) {
1366
+ if (stderr_buf != NULL) {
1367
+ munit_log_errno(MUNIT_LOG_ERROR, stderr, "unable to write to pipe");
1368
+ }
1369
+ exit(EXIT_FAILURE);
1370
+ }
1371
+ bytes_written += write_res;
1372
+ } while ((size_t) bytes_written < sizeof(report));
1373
+
1374
+ if (stderr_buf != NULL)
1375
+ fclose(stderr_buf);
1376
+ close(pipefd[1]);
1377
+
1378
+ exit(EXIT_SUCCESS);
1379
+ } else if (fork_pid == -1) {
1380
+ close(pipefd[0]);
1381
+ close(pipefd[1]);
1382
+ if (stderr_buf != NULL) {
1383
+ munit_log_errno(MUNIT_LOG_ERROR, stderr, "unable to fork");
1384
+ }
1385
+ report.errored++;
1386
+ result = MUNIT_ERROR;
1387
+ } else {
1388
+ close(pipefd[1]);
1389
+ do {
1390
+ read_res = read(pipefd[0], ((munit_uint8_t*) (&report)) + bytes_read, sizeof(report) - bytes_read);
1391
+ if (read_res < 1)
1392
+ break;
1393
+ bytes_read += read_res;
1394
+ } while (bytes_read < (ssize_t) sizeof(report));
1395
+
1396
+ changed_pid = waitpid(fork_pid, &status, 0);
1397
+
1398
+ if (MUNIT_LIKELY(changed_pid == fork_pid) && MUNIT_LIKELY(WIFEXITED(status))) {
1399
+ if (bytes_read != sizeof(report)) {
1400
+ munit_logf_internal(MUNIT_LOG_ERROR, stderr_buf, "child exited unexpectedly with status %d", WEXITSTATUS(status));
1401
+ report.errored++;
1402
+ } else if (WEXITSTATUS(status) != EXIT_SUCCESS) {
1403
+ munit_logf_internal(MUNIT_LOG_ERROR, stderr_buf, "child exited with status %d", WEXITSTATUS(status));
1404
+ report.errored++;
1405
+ }
1406
+ } else {
1407
+ if (WIFSIGNALED(status)) {
1408
+ #if defined(_XOPEN_VERSION) && (_XOPEN_VERSION >= 700)
1409
+ munit_logf_internal(MUNIT_LOG_ERROR, stderr_buf, "child killed by signal %d (%s)", WTERMSIG(status), strsignal(WTERMSIG(status)));
1410
+ #else
1411
+ munit_logf_internal(MUNIT_LOG_ERROR, stderr_buf, "child killed by signal %d", WTERMSIG(status));
1412
+ #endif
1413
+ } else if (WIFSTOPPED(status)) {
1414
+ munit_logf_internal(MUNIT_LOG_ERROR, stderr_buf, "child stopped by signal %d", WSTOPSIG(status));
1415
+ }
1416
+ report.errored++;
1417
+ }
1418
+
1419
+ close(pipefd[0]);
1420
+ waitpid(fork_pid, NULL, 0);
1421
+ }
1422
+ } else
1423
+ #endif
1424
+ {
1425
+ #if !defined(MUNIT_NO_BUFFER)
1426
+ const volatile int orig_stderr = munit_replace_stderr(stderr_buf);
1427
+ #endif
1428
+
1429
+ #if defined(MUNIT_THREAD_LOCAL)
1430
+ if (MUNIT_UNLIKELY(setjmp(munit_error_jmp_buf) != 0)) {
1431
+ result = MUNIT_FAIL;
1432
+ report.failed++;
1433
+ } else {
1434
+ munit_error_jmp_buf_valid = 1;
1435
+ result = munit_test_runner_exec(runner, test, params, &report);
1436
+ }
1437
+ #else
1438
+ result = munit_test_runner_exec(runner, test, params, &report);
1439
+ #endif
1440
+
1441
+ #if !defined(MUNIT_NO_BUFFER)
1442
+ munit_restore_stderr(orig_stderr);
1443
+ #endif
1444
+
1445
+ /* Here just so that the label is used on Windows and we don't get
1446
+ * a warning */
1447
+ goto print_result;
1448
+ }
1449
+
1450
+ print_result:
1451
+
1452
+ fputs("[ ", MUNIT_OUTPUT_FILE);
1453
+ if ((test->options & MUNIT_TEST_OPTION_TODO) == MUNIT_TEST_OPTION_TODO) {
1454
+ if (report.failed != 0 || report.errored != 0 || report.skipped != 0) {
1455
+ munit_test_runner_print_color(runner, MUNIT_RESULT_STRING_TODO, '3');
1456
+ result = MUNIT_OK;
1457
+ } else {
1458
+ munit_test_runner_print_color(runner, MUNIT_RESULT_STRING_ERROR, '1');
1459
+ if (MUNIT_LIKELY(stderr_buf != NULL))
1460
+ munit_log_internal(MUNIT_LOG_ERROR, stderr_buf, "Test marked TODO, but was successful.");
1461
+ runner->report.failed++;
1462
+ result = MUNIT_ERROR;
1463
+ }
1464
+ } else if (report.failed > 0) {
1465
+ munit_test_runner_print_color(runner, MUNIT_RESULT_STRING_FAIL, '1');
1466
+ runner->report.failed++;
1467
+ result = MUNIT_FAIL;
1468
+ } else if (report.errored > 0) {
1469
+ munit_test_runner_print_color(runner, MUNIT_RESULT_STRING_ERROR, '1');
1470
+ runner->report.errored++;
1471
+ result = MUNIT_ERROR;
1472
+ } else if (report.skipped > 0) {
1473
+ munit_test_runner_print_color(runner, MUNIT_RESULT_STRING_SKIP, '3');
1474
+ runner->report.skipped++;
1475
+ result = MUNIT_SKIP;
1476
+ } else if (report.successful > 1) {
1477
+ munit_test_runner_print_color(runner, MUNIT_RESULT_STRING_OK, '2');
1478
+ #if defined(MUNIT_ENABLE_TIMING)
1479
+ fputs(" ] [ ", MUNIT_OUTPUT_FILE);
1480
+ munit_print_time(MUNIT_OUTPUT_FILE, report.wall_clock / report.successful);
1481
+ fputs(" / ", MUNIT_OUTPUT_FILE);
1482
+ munit_print_time(MUNIT_OUTPUT_FILE, report.cpu_clock / report.successful);
1483
+ fprintf(MUNIT_OUTPUT_FILE, " CPU ]\n %-" MUNIT_XSTRINGIFY(MUNIT_TEST_NAME_LEN) "s Total: [ ", "");
1484
+ munit_print_time(MUNIT_OUTPUT_FILE, report.wall_clock);
1485
+ fputs(" / ", MUNIT_OUTPUT_FILE);
1486
+ munit_print_time(MUNIT_OUTPUT_FILE, report.cpu_clock);
1487
+ fputs(" CPU", MUNIT_OUTPUT_FILE);
1488
+ #endif
1489
+ runner->report.successful++;
1490
+ result = MUNIT_OK;
1491
+ } else if (report.successful > 0) {
1492
+ munit_test_runner_print_color(runner, MUNIT_RESULT_STRING_OK, '2');
1493
+ #if defined(MUNIT_ENABLE_TIMING)
1494
+ fputs(" ] [ ", MUNIT_OUTPUT_FILE);
1495
+ munit_print_time(MUNIT_OUTPUT_FILE, report.wall_clock);
1496
+ fputs(" / ", MUNIT_OUTPUT_FILE);
1497
+ munit_print_time(MUNIT_OUTPUT_FILE, report.cpu_clock);
1498
+ fputs(" CPU", MUNIT_OUTPUT_FILE);
1499
+ #endif
1500
+ runner->report.successful++;
1501
+ result = MUNIT_OK;
1502
+ }
1503
+ fputs(" ]\n", MUNIT_OUTPUT_FILE);
1504
+
1505
+ if (stderr_buf != NULL) {
1506
+ if (result == MUNIT_FAIL || result == MUNIT_ERROR || runner->show_stderr) {
1507
+ fflush(MUNIT_OUTPUT_FILE);
1508
+
1509
+ rewind(stderr_buf);
1510
+ munit_splice(fileno(stderr_buf), STDERR_FILENO);
1511
+
1512
+ fflush(stderr);
1513
+ }
1514
+
1515
+ fclose(stderr_buf);
1516
+ }
1517
+ }
1518
+
1519
+ static void
1520
+ munit_test_runner_run_test_wild(MunitTestRunner* runner,
1521
+ const MunitTest* test,
1522
+ const char* test_name,
1523
+ MunitParameter* params,
1524
+ MunitParameter* p) {
1525
+ const MunitParameterEnum* pe;
1526
+ char** values;
1527
+ MunitParameter* next;
1528
+
1529
+ for (pe = test->parameters ; pe != NULL && pe->name != NULL ; pe++) {
1530
+ if (p->name == pe->name)
1531
+ break;
1532
+ }
1533
+
1534
+ if (pe == NULL)
1535
+ return;
1536
+
1537
+ for (values = pe->values ; *values != NULL ; values++) {
1538
+ next = p + 1;
1539
+ p->value = *values;
1540
+ if (next->name == NULL) {
1541
+ munit_test_runner_run_test_with_params(runner, test, params);
1542
+ } else {
1543
+ munit_test_runner_run_test_wild(runner, test, test_name, params, next);
1544
+ }
1545
+ if (runner->fatal_failures && (runner->report.failed != 0 || runner->report.errored != 0))
1546
+ break;
1547
+ }
1548
+ }
1549
+
1550
+ /* Run a single test, with every combination of parameters
1551
+ * requested. */
1552
+ static void
1553
+ munit_test_runner_run_test(MunitTestRunner* runner,
1554
+ const MunitTest* test,
1555
+ const char* prefix) {
1556
+ char* test_name = munit_maybe_concat(NULL, (char*) prefix, (char*) test->name);
1557
+ /* The array of parameters to pass to
1558
+ * munit_test_runner_run_test_with_params */
1559
+ MunitParameter* params = NULL;
1560
+ size_t params_l = 0;
1561
+ /* Wildcard parameters are parameters which have possible values
1562
+ * specified in the test, but no specific value was passed to the
1563
+ * CLI. That means we want to run the test once for every
1564
+ * possible combination of parameter values or, if --single was
1565
+ * passed to the CLI, a single time with a random set of
1566
+ * parameters. */
1567
+ MunitParameter* wild_params = NULL;
1568
+ size_t wild_params_l = 0;
1569
+ const MunitParameterEnum* pe;
1570
+ const MunitParameter* cli_p;
1571
+ munit_bool filled;
1572
+ unsigned int possible;
1573
+ char** vals;
1574
+ size_t first_wild;
1575
+ const MunitParameter* wp;
1576
+ int pidx;
1577
+
1578
+ munit_rand_seed(runner->seed);
1579
+
1580
+ fprintf(MUNIT_OUTPUT_FILE, "%-" MUNIT_XSTRINGIFY(MUNIT_TEST_NAME_LEN) "s", test_name);
1581
+
1582
+ if (test->parameters == NULL) {
1583
+ /* No parameters. Simple, nice. */
1584
+ munit_test_runner_run_test_with_params(runner, test, NULL);
1585
+ } else {
1586
+ fputc('\n', MUNIT_OUTPUT_FILE);
1587
+
1588
+ for (pe = test->parameters ; pe != NULL && pe->name != NULL ; pe++) {
1589
+ /* Did we received a value for this parameter from the CLI? */
1590
+ filled = 0;
1591
+ for (cli_p = runner->parameters ; cli_p != NULL && cli_p->name != NULL ; cli_p++) {
1592
+ if (strcmp(cli_p->name, pe->name) == 0) {
1593
+ if (MUNIT_UNLIKELY(munit_parameters_add(&params_l, &params, pe->name, cli_p->value) != MUNIT_OK))
1594
+ goto cleanup;
1595
+ filled = 1;
1596
+ break;
1597
+ }
1598
+ }
1599
+ if (filled)
1600
+ continue;
1601
+
1602
+ /* Nothing from CLI, is the enum NULL/empty? We're not a
1603
+ * fuzzer… */
1604
+ if (pe->values == NULL || pe->values[0] == NULL)
1605
+ continue;
1606
+
1607
+ /* If --single was passed to the CLI, choose a value from the
1608
+ * list of possibilities randomly. */
1609
+ if (runner->single_parameter_mode) {
1610
+ possible = 0;
1611
+ for (vals = pe->values ; *vals != NULL ; vals++)
1612
+ possible++;
1613
+ /* We want the tests to be reproducible, even if you're only
1614
+ * running a single test, but we don't want every test with
1615
+ * the same number of parameters to choose the same parameter
1616
+ * number, so use the test name as a primitive salt. */
1617
+ pidx = munit_rand_at_most(munit_str_hash(test_name), possible - 1);
1618
+ if (MUNIT_UNLIKELY(munit_parameters_add(&params_l, &params, pe->name, pe->values[pidx]) != MUNIT_OK))
1619
+ goto cleanup;
1620
+ } else {
1621
+ /* We want to try every permutation. Put in a placeholder
1622
+ * entry, we'll iterate through them later. */
1623
+ if (MUNIT_UNLIKELY(munit_parameters_add(&wild_params_l, &wild_params, pe->name, NULL) != MUNIT_OK))
1624
+ goto cleanup;
1625
+ }
1626
+ }
1627
+
1628
+ if (wild_params_l != 0) {
1629
+ first_wild = params_l;
1630
+ for (wp = wild_params ; wp != NULL && wp->name != NULL ; wp++) {
1631
+ for (pe = test->parameters ; pe != NULL && pe->name != NULL && pe->values != NULL ; pe++) {
1632
+ if (strcmp(wp->name, pe->name) == 0) {
1633
+ if (MUNIT_UNLIKELY(munit_parameters_add(&params_l, &params, pe->name, pe->values[0]) != MUNIT_OK))
1634
+ goto cleanup;
1635
+ }
1636
+ }
1637
+ }
1638
+
1639
+ munit_test_runner_run_test_wild(runner, test, test_name, params, params + first_wild);
1640
+ } else {
1641
+ munit_test_runner_run_test_with_params(runner, test, params);
1642
+ }
1643
+
1644
+ cleanup:
1645
+ free(params);
1646
+ free(wild_params);
1647
+ }
1648
+
1649
+ munit_maybe_free_concat(test_name, prefix, test->name);
1650
+ }
1651
+
1652
+ /* Recurse through the suite and run all the tests. If a list of
1653
+ * tests to run was provied on the command line, run only those
1654
+ * tests. */
1655
+ static void
1656
+ munit_test_runner_run_suite(MunitTestRunner* runner,
1657
+ const MunitSuite* suite,
1658
+ const char* prefix) {
1659
+ size_t pre_l;
1660
+ char* pre = munit_maybe_concat(&pre_l, (char*) prefix, (char*) suite->prefix);
1661
+ const MunitTest* test;
1662
+ const char** test_name;
1663
+ const MunitSuite* child_suite;
1664
+
1665
+ /* Run the tests. */
1666
+ for (test = suite->tests ; test != NULL && test->test != NULL ; test++) {
1667
+ if (runner->tests != NULL) { /* Specific tests were requested on the CLI */
1668
+ for (test_name = runner->tests ; test_name != NULL && *test_name != NULL ; test_name++) {
1669
+ if ((pre_l == 0 || strncmp(pre, *test_name, pre_l) == 0) &&
1670
+ strncmp(test->name, *test_name + pre_l, strlen(*test_name + pre_l)) == 0) {
1671
+ munit_test_runner_run_test(runner, test, pre);
1672
+ if (runner->fatal_failures && (runner->report.failed != 0 || runner->report.errored != 0))
1673
+ goto cleanup;
1674
+ }
1675
+ }
1676
+ } else { /* Run all tests */
1677
+ munit_test_runner_run_test(runner, test, pre);
1678
+ }
1679
+ }
1680
+
1681
+ if (runner->fatal_failures && (runner->report.failed != 0 || runner->report.errored != 0))
1682
+ goto cleanup;
1683
+
1684
+ /* Run any child suites. */
1685
+ for (child_suite = suite->suites ; child_suite != NULL && child_suite->prefix != NULL ; child_suite++) {
1686
+ munit_test_runner_run_suite(runner, child_suite, pre);
1687
+ }
1688
+
1689
+ cleanup:
1690
+
1691
+ munit_maybe_free_concat(pre, prefix, suite->prefix);
1692
+ }
1693
+
1694
+ static void
1695
+ munit_test_runner_run(MunitTestRunner* runner) {
1696
+ munit_test_runner_run_suite(runner, runner->suite, NULL);
1697
+ }
1698
+
1699
+ static void
1700
+ munit_print_help(int argc, char* const argv[MUNIT_ARRAY_PARAM(argc + 1)], void* user_data, const MunitArgument arguments[]) {
1701
+ const MunitArgument* arg;
1702
+ (void) argc;
1703
+
1704
+ printf("USAGE: %s [OPTIONS...] [TEST...]\n\n", argv[0]);
1705
+ puts(" --seed SEED\n"
1706
+ " Value used to seed the PRNG. Must be a 32-bit integer in decimal\n"
1707
+ " notation with no separators (commas, decimals, spaces, etc.), or\n"
1708
+ " hexidecimal 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
+ }