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