Serene Runtime 1.0.0
C runtime for the Serene programming language
Loading...
Searching...
No Matches
acutest.h
Go to the documentation of this file.
1/*
2 * Acutest -- Another C/C++ Unit Test facility
3 * <https://github.com/mity/acutest>
4 *
5 * Copyright 2013-2023 Martin Mitáš
6 * Copyright 2019 Garrett D'Amore
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24 * IN THE SOFTWARE.
25 */
26
27#ifndef ACUTEST_H
28#define ACUTEST_H
29
30/* Try to auto-detect whether we need to disable C++ exception handling.
31 * If the detection fails, you may always define TEST_NO_EXCEPTIONS before
32 * including "acutest.h" manually. */
33#ifdef __cplusplus
34# if (__cplusplus >= 199711L && !defined __cpp_exceptions) || \
35 ((defined(__GNUC__) || defined(__clang__)) && !defined __EXCEPTIONS)
36# ifndef TEST_NO_EXCEPTIONS
37# define TEST_NO_EXCEPTIONS
38# endif
39# endif
40#endif
41
42/************************
43 *** Public interface ***
44 ************************/
45
46/* By default, "acutest.h" provides the main program entry point (function
47 * main()). However, if the test suite is composed of multiple source files
48 * which include "acutest.h", then this causes a problem of multiple main()
49 * definitions. To avoid this problem, #define macro TEST_NO_MAIN in all
50 * compilation units but one.
51 */
52
53/* Macro to specify list of unit tests in the suite.
54 * The unit test implementation MUST provide list of unit tests it implements
55 * with this macro:
56 *
57 * TEST_LIST = {
58 * { "test1_name", test1_func_ptr },
59 * { "test2_name", test2_func_ptr },
60 * ...
61 * { NULL, NULL } // zeroed record marking the end of the list
62 * };
63 *
64 * The list specifies names of each test (must be unique) and pointer to
65 * a function implementing it. The function does not take any arguments
66 * and has no return values, i.e. every test function has to be compatible
67 * with this prototype:
68 *
69 * void test_func(void);
70 *
71 * Note the list has to be ended with a zeroed record.
72 */
73#define TEST_LIST const struct acutest_test_ acutest_list_[]
74
75/* Macros for testing whether an unit test succeeds or fails. These macros
76 * can be used arbitrarily in functions implementing the unit tests.
77 *
78 * If any condition fails throughout execution of a test, the test fails.
79 *
80 * TEST_CHECK takes only one argument (the condition), TEST_CHECK_ allows
81 * also to specify an error message to print out if the condition fails.
82 * (It expects printf-like format string and its parameters). The macros
83 * return non-zero (condition passes) or 0 (condition fails).
84 *
85 * That can be useful when more conditions should be checked only if some
86 * preceding condition passes, as illustrated in this code snippet:
87 *
88 * SomeStruct* ptr = allocate_some_struct();
89 * if(TEST_CHECK(ptr != NULL)) {
90 * TEST_CHECK(ptr->member1 < 100);
91 * TEST_CHECK(ptr->member2 > 200);
92 * }
93 */
94#define TEST_CHECK_(cond, ...) \
95 acutest_check_(!!(cond), __FILE__, __LINE__, __VA_ARGS__)
96#define TEST_CHECK(cond) \
97 acutest_check_(!!(cond), __FILE__, __LINE__, "%s", #cond)
98
99/* These macros are the same as TEST_CHECK_ and TEST_CHECK except that if the
100 * condition fails, the currently executed unit test is immediately aborted.
101 *
102 * That is done either by calling abort() if the unit test is executed as a
103 * child process; or via longjmp() if the unit test is executed within the
104 * main Acutest process.
105 *
106 * As a side effect of such abortion, your unit tests may cause memory leaks,
107 * unflushed file descriptors, and other phenomena caused by the abortion.
108 *
109 * Therefore you should not use these as a general replacement for TEST_CHECK.
110 * Use it with some caution, especially if your test causes some other side
111 * effects to the outside world (e.g. communicating with some server, inserting
112 * into a database etc.).
113 */
114#define TEST_ASSERT_(cond, ...) \
115 do { \
116 if (!acutest_check_(!!(cond), __FILE__, __LINE__, __VA_ARGS__)) \
117 acutest_abort_(); \
118 } while (0)
119#define TEST_ASSERT(cond) \
120 do { \
121 if (!acutest_check_(!!(cond), __FILE__, __LINE__, "%s", #cond)) \
122 acutest_abort_(); \
123 } while (0)
124
125#ifdef __cplusplus
126# ifndef TEST_NO_EXCEPTIONS
127/* Macros to verify that the code (the 1st argument) throws exception of given
128 * type (the 2nd argument). (Note these macros are only available in C++.)
129 *
130 * TEST_EXCEPTION_ is like TEST_EXCEPTION but accepts custom printf-like
131 * message.
132 *
133 * For example:
134 *
135 * TEST_EXCEPTION(function_that_throw(), ExpectedExceptionType);
136 *
137 * If the function_that_throw() throws ExpectedExceptionType, the check passes.
138 * If the function throws anything incompatible with ExpectedExceptionType
139 * (or if it does not thrown an exception at all), the check fails.
140 */
141# define TEST_EXCEPTION(code, exctype) \
142 do { \
143 bool exc_ok_ = false; \
144 const char *msg_ = NULL; \
145 try { \
146 code; \
147 msg_ = "No exception thrown."; \
148 } catch (exctype const &) { \
149 exc_ok_ = true; \
150 } catch (...) { \
151 msg_ = "Unexpected exception thrown."; \
152 } \
153 acutest_check_(exc_ok_, __FILE__, __LINE__, \
154 #code " throws " #exctype); \
155 if (msg_ != NULL) \
156 acutest_message_("%s", msg_); \
157 } while (0)
158# define TEST_EXCEPTION_(code, exctype, ...) \
159 do { \
160 bool exc_ok_ = false; \
161 const char *msg_ = NULL; \
162 try { \
163 code; \
164 msg_ = "No exception thrown."; \
165 } catch (exctype const &) { \
166 exc_ok_ = true; \
167 } catch (...) { \
168 msg_ = "Unexpected exception thrown."; \
169 } \
170 acutest_check_(exc_ok_, __FILE__, __LINE__, __VA_ARGS__); \
171 if (msg_ != NULL) \
172 acutest_message_("%s", msg_); \
173 } while (0)
174# endif /* #ifndef TEST_NO_EXCEPTIONS */
175#endif /* #ifdef __cplusplus */
176
177/* Sometimes it is useful to split execution of more complex unit tests to some
178 * smaller parts and associate those parts with some names.
179 *
180 * This is especially handy if the given unit test is implemented as a loop
181 * over some vector of multiple testing inputs. Using these macros allow to use
182 * sort of subtitle for each iteration of the loop (e.g. outputting the input
183 * itself or a name associated to it), so that if any TEST_CHECK condition
184 * fails in the loop, it can be easily seen which iteration triggers the
185 * failure, without the need to manually output the iteration-specific data in
186 * every single TEST_CHECK inside the loop body.
187 *
188 * TEST_CASE allows to specify only single string as the name of the case,
189 * TEST_CASE_ provides all the power of printf-like string formatting.
190 *
191 * Note that the test cases cannot be nested. Starting a new test case ends
192 * implicitly the previous one. To end the test case explicitly (e.g. to end
193 * the last test case after exiting the loop), you may use TEST_CASE(NULL).
194 */
195#define TEST_CASE_(...) acutest_case_(__VA_ARGS__)
196#define TEST_CASE(name) acutest_case_("%s", name)
197
198/* Maximal output per TEST_CASE call. Longer messages are cut.
199 * You may define another limit prior including "acutest.h"
200 */
201#ifndef TEST_CASE_MAXSIZE
202# define TEST_CASE_MAXSIZE 64
203#endif
204
205/* printf-like macro for outputting an extra information about a failure.
206 *
207 * Intended use is to output some computed output versus the expected value,
208 * e.g. like this:
209 *
210 * if(!TEST_CHECK(produced == expected)) {
211 * TEST_MSG("Expected: %d", expected);
212 * TEST_MSG("Produced: %d", produced);
213 * }
214 *
215 * Note the message is only written down if the most recent use of any checking
216 * macro (like e.g. TEST_CHECK or TEST_EXCEPTION) in the current test failed.
217 * This means the above is equivalent to just this:
218 *
219 * TEST_CHECK(produced == expected);
220 * TEST_MSG("Expected: %d", expected);
221 * TEST_MSG("Produced: %d", produced);
222 *
223 * The macro can deal with multi-line output fairly well. It also automatically
224 * adds a final new-line if there is none present.
225 */
226#define TEST_MSG(...) acutest_message_(__VA_ARGS__)
227
228/* Maximal output per TEST_MSG call. Longer messages are cut.
229 * You may define another limit prior including "acutest.h"
230 */
231#ifndef TEST_MSG_MAXSIZE
232# define TEST_MSG_MAXSIZE 1024
233#endif
234
235/* Macro for dumping a block of memory.
236 *
237 * Its intended use is very similar to what TEST_MSG is for, but instead of
238 * generating any printf-like message, this is for dumping raw block of a
239 * memory in a hexadecimal form:
240 *
241 * TEST_CHECK(size_produced == size_expected &&
242 * memcmp(addr_produced, addr_expected, size_produced) == 0);
243 * TEST_DUMP("Expected:", addr_expected, size_expected);
244 * TEST_DUMP("Produced:", addr_produced, size_produced);
245 */
246#define TEST_DUMP(title, addr, size) acutest_dump_(title, addr, size)
247
248/* Maximal output per TEST_DUMP call (in bytes to dump). Longer blocks are cut.
249 * You may define another limit prior including "acutest.h"
250 */
251#ifndef TEST_DUMP_MAXSIZE
252# define TEST_DUMP_MAXSIZE 1024
253#endif
254
255/* Macros for marking the test as SKIPPED.
256 * Note it can only be used at the beginning of a test, before any other
257 * checking.
258 *
259 * Once used, the best practice is to return from the test routine as soon
260 * as possible.
261 */
262#define TEST_SKIP(...) acutest_skip_(__FILE__, __LINE__, __VA_ARGS__)
263
264/* Common test initialisation/clean-up
265 *
266 * In some test suites, it may be needed to perform some sort of the same
267 * initialization and/or clean-up in all the tests.
268 *
269 * Such test suites may use macros TEST_INIT and/or TEST_FINI prior including
270 * this header. The expansion of the macro is then used as a body of helper
271 * function called just before executing every single (TEST_INIT) or just after
272 * it ends (TEST_FINI).
273 *
274 * Examples of various ways how to use the macro TEST_INIT:
275 *
276 * #define TEST_INIT my_init_func();
277 * #define TEST_INIT my_init_func() // Works even without the
278 * semicolon #define TEST_INIT setlocale(LC_ALL, NULL); #define TEST_INIT
279 * { setlocale(LC_ALL, NULL); my_init_func(); }
280 *
281 * TEST_FINI is to be used in the same way.
282 */
283
284/**********************
285 *** Implementation ***
286 **********************/
287
288/* The unit test files should not rely on anything below. */
289
290#include <stdlib.h>
291
292/* Enable the use of the non-standard keyword __attribute__ to silence warnings
293 * under some compilers */
294#if defined(__GNUC__) || defined(__clang__)
295# define ACUTEST_ATTRIBUTE_(attr) __attribute__((attr))
296#else
297# define ACUTEST_ATTRIBUTE_(attr)
298#endif
299
300#ifdef __cplusplus
301extern "C" {
302#endif
303
315
316int acutest_check_(int cond, const char *file, int line, const char *fmt, ...);
317void acutest_case_(const char *fmt, ...);
318void acutest_message_(const char *fmt, ...);
319void acutest_dump_(const char *title, const void *addr, size_t size);
320void acutest_abort_(void) ACUTEST_ATTRIBUTE_(noreturn);
321#ifdef __cplusplus
322} /* extern "C" */
323#endif
324
325#ifndef TEST_NO_MAIN
326
327# include <stdarg.h>
328# include <stdio.h>
329
330# include <ctype.h>
331# include <setjmp.h>
332# include <string.h>
333
334# if defined(unix) || defined(__unix__) || defined(__unix) || \
335 defined(__APPLE__)
336# define ACUTEST_UNIX_ 1
337# include <errno.h>
338# include <libgen.h>
339# include <signal.h>
340# include <sys/types.h>
341# include <sys/wait.h>
342# include <time.h>
343# include <unistd.h>
344
345# if defined CLOCK_PROCESS_CPUTIME_ID && defined CLOCK_MONOTONIC
346# define ACUTEST_HAS_POSIX_TIMER_ 1
347# endif
348# endif
349
350# if defined(_gnu_linux_) || defined(__linux__)
351# define ACUTEST_LINUX_ 1
352# include <fcntl.h>
353# include <sys/stat.h>
354# endif
355
356# if defined(_WIN32) || defined(__WIN32__) || defined(__WINDOWS__)
357# define ACUTEST_WIN_ 1
358# include <io.h>
359# include <windows.h>
360# endif
361
362# if defined(__APPLE__)
363# define ACUTEST_MACOS_
364# include <stdbool.h>
365
366# include <assert.h>
367# include <sys/sysctl.h>
368# include <sys/types.h>
369# include <unistd.h>
370# endif
371
372# ifdef __cplusplus
373# ifndef TEST_NO_EXCEPTIONS
374# include <exception>
375# endif
376# endif
377
378# ifdef __has_include
379# if __has_include(<valgrind.h>)
380# include <valgrind.h>
381# endif
382# endif
383
384/* Note our global private identifiers end with '_' to mitigate risk of clash
385 * with the unit tests implementation. */
386
387# ifdef __cplusplus
388extern "C" {
389# endif
390
391# ifdef _MSC_VER
392/* In the multi-platform code like ours, we cannot use the non-standard
393 * "safe" functions from Microsoft C lib like e.g. sprintf_s() instead of
394 * standard sprintf(). Hence, lets disable the warning C4996. */
395# pragma warning(push)
396# pragma warning(disable : 4996)
397# endif
398
400 const char *name;
401 void (*func)(void);
402};
403
408
409extern const struct acutest_test_ acutest_list_[];
410
411static char *acutest_argv0_ = NULL;
412static int acutest_list_size_ = 0;
414static int acutest_no_exec_ = -1;
415static int acutest_no_summary_ = 0;
416static int acutest_tap_ = 0;
418static int acutest_worker_ = 0;
420static int acutest_cond_failed_ = 0;
421static FILE *acutest_xml_output_ = NULL;
422
423static const struct acutest_test_ *acutest_current_test_ = NULL;
428static char acutest_test_skip_reason_[256] = "";
433static int acutest_colorize_ = 0;
434static int acutest_timer_ = 0;
435
438
439static int acutest_count_(enum acutest_state_ state) {
440 int i, n;
441
442 for (i = 0, n = 0; i < acutest_list_size_; i++) {
443 if (acutest_test_data_[i].state == state)
444 n++;
445 }
446
447 return n;
448}
449
450static void acutest_cleanup_(void) { free((void *)acutest_test_data_); }
451
452static void ACUTEST_ATTRIBUTE_(noreturn) acutest_exit_(int exit_code) {
454 exit(exit_code);
455}
456
457# if defined ACUTEST_WIN_
458typedef LARGE_INTEGER acutest_timer_type_;
459static LARGE_INTEGER acutest_timer_freq_;
462
463static void acutest_timer_init_(void) {
464 QueryPerformanceFrequency(&acutest_timer_freq_);
465}
466
467static void acutest_timer_get_time_(LARGE_INTEGER *ts) {
468 QueryPerformanceCounter(ts);
469}
470
471static double acutest_timer_diff_(LARGE_INTEGER start, LARGE_INTEGER end) {
472 double duration = (double)(end.QuadPart - start.QuadPart);
473 duration /= (double)acutest_timer_freq_.QuadPart;
474 return duration;
475}
476
477static void acutest_timer_print_diff_(void) {
478 printf("%.6lf secs",
480}
481# elif defined ACUTEST_HAS_POSIX_TIMER_
482static clockid_t acutest_timer_id_;
483typedef struct timespec acutest_timer_type_;
486
487static void acutest_timer_init_(void) {
488 if (acutest_timer_ == 1)
489 acutest_timer_id_ = CLOCK_MONOTONIC;
490 else if (acutest_timer_ == 2)
491 acutest_timer_id_ = CLOCK_PROCESS_CPUTIME_ID;
492}
493
494static void acutest_timer_get_time_(struct timespec *ts) {
495 clock_gettime(acutest_timer_id_, ts);
496}
497
498static double acutest_timer_diff_(struct timespec start, struct timespec end) {
499 return (double)(end.tv_sec - start.tv_sec) +
500 (double)(end.tv_nsec - start.tv_nsec) / 1e9;
501}
502
503static void acutest_timer_print_diff_(void) {
504 printf("%.6lf secs",
506}
507# else
511
513
514static void acutest_timer_get_time_(int *ts) { (void)ts; }
515
516static double acutest_timer_diff_(int start, int end) {
517 (void)start;
518 (void)end;
519 return 0.0;
520}
521
522static void acutest_timer_print_diff_(void) {}
523# endif
524
525# define ACUTEST_COLOR_DEFAULT_ 0
526# define ACUTEST_COLOR_RED_ 1
527# define ACUTEST_COLOR_GREEN_ 2
528# define ACUTEST_COLOR_YELLOW_ 3
529# define ACUTEST_COLOR_DEFAULT_INTENSIVE_ 10
530# define ACUTEST_COLOR_RED_INTENSIVE_ 11
531# define ACUTEST_COLOR_GREEN_INTENSIVE_ 12
532# define ACUTEST_COLOR_YELLOW_INTENSIVE_ 13
533
534static int ACUTEST_ATTRIBUTE_(format(printf, 2, 3))
535 acutest_colored_printf_(int color, const char *fmt, ...) {
536 va_list args;
537 char buffer[256];
538 int n;
539
543 buffer[sizeof(buffer) - 1] = '\0';
544
546 return printf("%s", buffer);
547 }
548
549# if defined ACUTEST_UNIX_
550 {
551 const char *col_str;
552 switch (color) {
554 col_str = "\033[0;31m";
555 break;
557 col_str = "\033[0;32m";
558 break;
560 col_str = "\033[0;33m";
561 break;
563 col_str = "\033[1;31m";
564 break;
566 col_str = "\033[1;32m";
567 break;
569 col_str = "\033[1;33m";
570 break;
572 col_str = "\033[1m";
573 break;
574 default:
575 col_str = "\033[0m";
576 break;
577 }
578 printf("%s", col_str);
579 n = printf("%s", buffer);
580 printf("\033[0m");
581 return n;
582 }
583# elif defined ACUTEST_WIN_
584 {
585 HANDLE h;
586 CONSOLE_SCREEN_BUFFER_INFO info;
587 WORD attr;
588
589 h = GetStdHandle(STD_OUTPUT_HANDLE);
590 GetConsoleScreenBufferInfo(h, &info);
591
592 switch (color) {
594 attr = FOREGROUND_RED;
595 break;
597 attr = FOREGROUND_GREEN;
598 break;
600 attr = FOREGROUND_RED | FOREGROUND_GREEN;
601 break;
603 attr = FOREGROUND_RED | FOREGROUND_INTENSITY;
604 break;
606 attr = FOREGROUND_GREEN | FOREGROUND_INTENSITY;
607 break;
609 attr = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED |
610 FOREGROUND_INTENSITY;
611 break;
613 attr = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY;
614 break;
615 default:
616 attr = 0;
617 break;
618 }
619 if (attr != 0)
620 SetConsoleTextAttribute(h, attr);
621 n = printf("%s", buffer);
622 SetConsoleTextAttribute(h, info.wAttributes);
623 return n;
624 }
625# else
626 n = printf("%s", buffer);
627 return n;
628# endif
629}
630
631static const char *acutest_basename_(const char *path) {
632 const char *name;
633
634 name = strrchr(path, '/');
635 if (name != NULL)
636 name++;
637 else
638 name = path;
639
640# ifdef ACUTEST_WIN_
641 {
642 const char *alt_name;
643
644 alt_name = strrchr(path, '\\');
645 if (alt_name != NULL)
646 alt_name++;
647 else
648 alt_name = path;
649
650 if (alt_name > name)
651 name = alt_name;
652 }
653# endif
654
655 return name;
656}
657
658static void acutest_begin_test_line_(const struct acutest_test_ *test) {
659 if (!acutest_tap_) {
660 if (acutest_verbose_level_ >= 3) {
661 acutest_colored_printf_(ACUTEST_COLOR_DEFAULT_INTENSIVE_, "Test %s:\n",
662 test->name);
664 } else if (acutest_verbose_level_ >= 1) {
665 int n;
666 char spaces[48];
667
668 n = acutest_colored_printf_(ACUTEST_COLOR_DEFAULT_INTENSIVE_,
669 "Test %s... ", test->name);
670 memset(spaces, ' ', sizeof(spaces));
671 if (n < (int)sizeof(spaces))
672 printf("%.*s", (int)sizeof(spaces) - n, spaces);
673 } else {
675 }
676 }
677}
678
680 if (acutest_tap_) {
681 printf("%s %d - %s%s\n",
682 (state == ACUTEST_STATE_SUCCESS || state == ACUTEST_STATE_SKIPPED)
683 ? "ok"
684 : "not ok",
686 (state == ACUTEST_STATE_SKIPPED) ? " # SKIP" : "");
687
688 if (state == ACUTEST_STATE_SUCCESS && acutest_timer_) {
689 printf("# Duration: ");
691 printf("\n");
692 }
693 } else {
694 int color;
695 const char *str;
696
697 switch (state) {
700 str = "OK";
701 break;
704 str = "SKIPPED";
705 break;
706 case ACUTEST_STATE_FAILED: /* Fall through. */
707 default:
709 str = "FAILED";
710 break;
711 }
712
713 printf("[ ");
714 acutest_colored_printf_(color, "%s", str);
715 printf(" ]");
716
717 if (state == ACUTEST_STATE_SUCCESS && acutest_timer_) {
718 printf(" ");
720 }
721
722 printf("\n");
723 }
724}
725
726static void acutest_line_indent_(int level) {
727 static const char spaces[] = " ";
728 int n = level * 2;
729
730 if (acutest_tap_ && n > 0) {
731 n--;
732 printf("#");
733 }
734
735 while (n > 16) {
736 printf("%s", spaces);
737 n -= 16;
738 }
739 printf("%.*s", n, spaces);
740}
741
742void ACUTEST_ATTRIBUTE_(format(printf, 3, 4))
743 acutest_skip_(const char *file, int line, const char *fmt, ...) {
744 va_list args;
746
747 va_start(args, fmt);
749 args);
750 va_end(args);
752
753 /* Remove final dot, if provided; that collides with our other logic. */
757
759 acutest_check_(0, file, line, "Cannot skip, already performed some checks");
760 return;
761 }
762
764 const char *result_str = "skipped";
766
770
772
773 if (file != NULL) {
775 printf("%s:%d: ", file, line);
776 }
777
778 printf("%s... ", acutest_test_skip_reason_);
779 acutest_colored_printf_(result_color, "%s", result_str);
780 printf("\n");
782 }
783
785}
786
787int ACUTEST_ATTRIBUTE_(format(printf, 4, 5))
788 acutest_check_(int cond, const char *file, int line, const char *fmt, ...) {
789 const char *result_str;
792
794 /* We've skipped the test. We shouldn't be here: The test implementation
795 * should have already return before. So lets suppress the following
796 * output. */
797 cond = 1;
798 goto skip_check;
799 }
800
801 if (cond) {
802 result_str = "ok";
804 verbose_level = 3;
805 } else {
808
811
812 result_str = "failed";
814 verbose_level = 2;
815 }
816
818 va_list args;
819
822 acutest_colored_printf_(ACUTEST_COLOR_DEFAULT_INTENSIVE_, "Case %s:\n",
826 }
827
829 if (file != NULL) {
831 printf("%s:%d: ", file, line);
832 }
833
834 va_start(args, fmt);
835 vprintf(fmt, args);
836 va_end(args);
837
838 printf("... ");
839 acutest_colored_printf_(result_color, "%s", result_str);
840 printf("\n");
842 }
843
845
846skip_check:
847 acutest_cond_failed_ = (cond == 0);
849}
850
851void ACUTEST_ATTRIBUTE_(format(printf, 1, 2))
852 acutest_case_(const char *fmt, ...) {
853 va_list args;
854
856 return;
857
862
863 if (fmt == NULL)
864 return;
865
866 va_start(args, fmt);
868 va_end(args);
869 acutest_case_name_[sizeof(acutest_case_name_) - 1] = '\0';
870
871 if (acutest_verbose_level_ >= 3) {
873 acutest_colored_printf_(ACUTEST_COLOR_DEFAULT_INTENSIVE_, "Case %s:\n",
877 }
878}
879
880void ACUTEST_ATTRIBUTE_(format(printf, 1, 2))
881 acutest_message_(const char *fmt, ...) {
883 char *line_beg;
884 char *line_end;
885 va_list args;
886
888 return;
889
890 /* We allow extra message only when something is already wrong in the
891 * current test. */
893 return;
894
895 va_start(args, fmt);
897 va_end(args);
898 buffer[TEST_MSG_MAXSIZE - 1] = '\0';
899
901 while (1) {
902 line_end = strchr(line_beg, '\n');
903 if (line_end == NULL)
904 break;
906 printf("%.*s\n", (int)(line_end - line_beg), line_beg);
907 line_beg = line_end + 1;
908 }
909 if (line_beg[0] != '\0') {
911 printf("%s\n", line_beg);
912 }
913}
914
915void acutest_dump_(const char *title, const void *addr, size_t size) {
916 static const size_t BYTES_PER_LINE = 16;
917 size_t line_beg;
918 size_t truncate = 0;
919
921 return;
922
923 /* We allow extra message only when something is already wrong in the
924 * current test. */
926 return;
927
928 if (size > TEST_DUMP_MAXSIZE) {
929 truncate = size - TEST_DUMP_MAXSIZE;
930 size = TEST_DUMP_MAXSIZE;
931 }
932
934 printf((title[strlen(title) - 1] == ':') ? "%s\n" : "%s:\n", title);
935
936 for (line_beg = 0; line_beg < size; line_beg += BYTES_PER_LINE) {
937 size_t line_end = line_beg + BYTES_PER_LINE;
938 size_t off;
939
941 printf("%08lx: ", (unsigned long)line_beg);
942 for (off = line_beg; off < line_end; off++) {
943 if (off < size)
944 printf(" %02x", ((const unsigned char *)addr)[off]);
945 else
946 printf(" ");
947 }
948
949 printf(" ");
950 for (off = line_beg; off < line_end; off++) {
951 unsigned char byte = ((const unsigned char *)addr)[off];
952 if (off < size)
953 printf("%c", (iscntrl(byte) ? '.' : byte));
954 else
955 break;
956 }
957
958 printf("\n");
959 }
960
961 if (truncate > 0) {
963 printf(" ... (and more %u bytes)\n", (unsigned)truncate);
964 }
965}
966
967/* This is called just before each test */
968static void acutest_init_(const char *test_name) {
969# ifdef TEST_INIT
970 TEST_INIT; /* Allow for a single unterminated function call */
971# endif
972
973 /* Suppress any warnings about unused variable. */
974 (void)test_name;
975}
976
977/* This is called after each test */
978static void acutest_fini_(const char *test_name) {
979# ifdef TEST_FINI
980 TEST_FINI; /* Allow for a single unterminated function call */
981# endif
982
983 /* Suppress any warnings about unused variable. */
984 (void)test_name;
985}
986
987void acutest_abort_(void) {
989 longjmp(acutest_abort_jmp_buf_, 1);
990 } else {
991 if (acutest_current_test_ != NULL)
993 fflush(stdout);
994 fflush(stderr);
995 acutest_exit_(ACUTEST_STATE_FAILED);
996 }
997}
998
999static void acutest_list_names_(void) {
1000 const struct acutest_test_ *test;
1001
1002 printf("Unit tests:\n");
1003 for (test = &acutest_list_[0]; test->func != NULL; test++)
1004 printf(" %s\n", test->name);
1005}
1006
1007static int acutest_name_contains_word_(const char *name, const char *pattern) {
1008 static const char word_delim[] = " \t-_/.,:;";
1009 const char *substr;
1010 size_t pattern_len;
1011
1012 pattern_len = strlen(pattern);
1013
1014 substr = strstr(name, pattern);
1015 while (substr != NULL) {
1016 int starts_on_word_boundary =
1017 (substr == name || strchr(word_delim, substr[-1]) != NULL);
1018 int ends_on_word_boundary =
1019 (substr[pattern_len] == '\0' ||
1020 strchr(word_delim, substr[pattern_len]) != NULL);
1021
1022 if (starts_on_word_boundary && ends_on_word_boundary)
1023 return 1;
1024
1025 substr = strstr(substr + 1, pattern);
1026 }
1027
1028 return 0;
1029}
1030
1031static int acutest_select_(const char *pattern) {
1032 int i;
1033 int n = 0;
1034
1035 /* Try exact match. */
1036 for (i = 0; i < acutest_list_size_; i++) {
1037 if (strcmp(acutest_list_[i].name, pattern) == 0) {
1039 n++;
1040 break;
1041 }
1042 }
1043 if (n > 0)
1044 return n;
1045
1046 /* Try word match. */
1047 for (i = 0; i < acutest_list_size_; i++) {
1050 n++;
1051 }
1052 }
1053 if (n > 0)
1054 return n;
1055
1056 /* Try relaxed match. */
1057 for (i = 0; i < acutest_list_size_; i++) {
1058 if (strstr(acutest_list_[i].name, pattern) != NULL) {
1060 n++;
1061 }
1062 }
1063
1064 return n;
1065}
1066
1067/* Called if anything goes bad in Acutest, or if the unit test ends in other
1068 * way then by normal returning from its function (e.g. exception or some
1069 * abnormal child process termination). */
1070static void ACUTEST_ATTRIBUTE_(format(printf, 1, 2))
1071 acutest_error_(const char *fmt, ...) {
1072 if (acutest_verbose_level_ == 0)
1073 return;
1074
1075 if (acutest_verbose_level_ >= 2) {
1076 va_list args;
1077
1079 if (acutest_verbose_level_ >= 3)
1080 acutest_colored_printf_(ACUTEST_COLOR_RED_INTENSIVE_, "ERROR: ");
1081 va_start(args, fmt);
1082 vprintf(fmt, args);
1083 va_end(args);
1084 printf("\n");
1085 }
1086
1087 if (acutest_verbose_level_ >= 3) {
1088 printf("\n");
1089 }
1090}
1091
1092/* Call directly the given test unit function. */
1093static enum acutest_state_ acutest_do_run_(const struct acutest_test_ *test,
1094 int index) {
1096
1097 acutest_current_test_ = test;
1098 acutest_current_index_ = index;
1104
1105# ifdef __cplusplus
1106# ifndef TEST_NO_EXCEPTIONS
1107 try {
1108# endif
1109# endif
1110 acutest_init_(test->name);
1112
1113 /* This is good to do in case the test unit crashes. */
1114 fflush(stdout);
1115 fflush(stderr);
1116
1117 if (!acutest_worker_) {
1119 if (setjmp(acutest_abort_jmp_buf_) != 0)
1120 goto aborted;
1121 }
1122
1124 test->func();
1125
1126 aborted:
1129
1130 if (acutest_test_failures_ > 0)
1131 state = ACUTEST_STATE_FAILED;
1132 else if (acutest_test_skip_count_ > 0)
1133 state = ACUTEST_STATE_SKIPPED;
1134 else
1135 state = ACUTEST_STATE_SUCCESS;
1136
1139
1140 if (acutest_verbose_level_ >= 3) {
1142 switch (state) {
1144 acutest_colored_printf_(ACUTEST_COLOR_GREEN_INTENSIVE_, "SUCCESS: ");
1145 printf("All conditions have passed.\n");
1146
1147 if (acutest_timer_) {
1149 printf("Duration: ");
1151 printf("\n");
1152 }
1153 break;
1154
1156 acutest_colored_printf_(ACUTEST_COLOR_YELLOW_INTENSIVE_, "SKIPPED: ");
1157 printf("%s.\n", acutest_test_skip_reason_);
1158 break;
1159
1160 default:
1161 acutest_colored_printf_(ACUTEST_COLOR_RED_INTENSIVE_, "FAILED: ");
1162 printf("%d condition%s %s failed.\n", acutest_test_failures_,
1163 (acutest_test_failures_ == 1) ? "" : "s",
1164 (acutest_test_failures_ == 1) ? "has" : "have");
1165 break;
1166 }
1167 printf("\n");
1168 }
1169
1170# ifdef __cplusplus
1171# ifndef TEST_NO_EXCEPTIONS
1172 } catch (std::exception &e) {
1173 const char *what = e.what();
1174 acutest_check_(0, NULL, 0, "Threw std::exception");
1175 if (what != NULL)
1176 acutest_message_("std::exception::what(): %s", what);
1177
1178 if (acutest_verbose_level_ >= 3) {
1180 acutest_colored_printf_(ACUTEST_COLOR_RED_INTENSIVE_, "FAILED: ");
1181 printf("C++ exception.\n\n");
1182 }
1183 } catch (...) {
1184 acutest_check_(0, NULL, 0, "Threw an exception");
1185
1186 if (acutest_verbose_level_ >= 3) {
1188 acutest_colored_printf_(ACUTEST_COLOR_RED_INTENSIVE_, "FAILED: ");
1189 printf("C++ exception.\n\n");
1190 }
1191 }
1192# endif
1193# endif
1194
1195 acutest_fini_(test->name);
1196 acutest_case_(NULL);
1197 acutest_current_test_ = NULL;
1198
1199 return state;
1200}
1201
1202/* Trigger the unit test. If possible (and not suppressed) it starts a child
1203 * process who calls acutest_do_run_(), otherwise it calls acutest_do_run_()
1204 * directly. */
1205static void acutest_run_(const struct acutest_test_ *test, int index,
1206 int master_index) {
1208 acutest_timer_type_ start, end;
1209
1210 acutest_current_test_ = test;
1213
1214 if (!acutest_no_exec_) {
1215
1216# if defined(ACUTEST_UNIX_)
1217
1218 pid_t pid;
1219 int exit_code;
1220
1221 /* Make sure the child starts with empty I/O buffers. */
1222 fflush(stdout);
1223 fflush(stderr);
1224
1225 pid = fork();
1226 if (pid == (pid_t)-1) {
1227 acutest_error_("Cannot fork. %s [%d]", strerror(errno), errno);
1228 } else if (pid == 0) {
1229 /* Child: Do the test. */
1230 acutest_worker_ = 1;
1231 state = acutest_do_run_(test, index);
1232 acutest_exit_((int)state);
1233 } else {
1234 /* Parent: Wait until child terminates and analyze its exit code. */
1235 waitpid(pid, &exit_code, 0);
1236 if (WIFEXITED(exit_code)) {
1237 state = (enum acutest_state_)WEXITSTATUS(exit_code);
1238 } else if (WIFSIGNALED(exit_code)) {
1239 char tmp[32];
1240 const char *signame;
1241 switch (WTERMSIG(exit_code)) {
1242 case SIGINT:
1243 signame = "SIGINT";
1244 break;
1245 case SIGHUP:
1246 signame = "SIGHUP";
1247 break;
1248 case SIGQUIT:
1249 signame = "SIGQUIT";
1250 break;
1251 case SIGABRT:
1252 signame = "SIGABRT";
1253 break;
1254 case SIGKILL:
1255 signame = "SIGKILL";
1256 break;
1257 case SIGSEGV:
1258 signame = "SIGSEGV";
1259 break;
1260 case SIGILL:
1261 signame = "SIGILL";
1262 break;
1263 case SIGTERM:
1264 signame = "SIGTERM";
1265 break;
1266 default:
1267 snprintf(tmp, sizeof(tmp), "signal %d", WTERMSIG(exit_code));
1268 signame = tmp;
1269 break;
1270 }
1271 acutest_error_("Test interrupted by %s.", signame);
1272 } else {
1273 acutest_error_("Test ended in an unexpected way [%d].", exit_code);
1274 }
1275 }
1276
1277# elif defined(ACUTEST_WIN_)
1278
1279 char buffer[512] = {0};
1280 STARTUPINFOA startupInfo;
1281 PROCESS_INFORMATION processInfo;
1282 DWORD exitCode;
1283
1284 /* Windows has no fork(). So we propagate all info into the child
1285 * through a command line arguments. */
1286 snprintf(buffer, sizeof(buffer),
1287 "%s --worker=%d %s --no-exec --no-summary %s --verbose=%d "
1288 "--color=%s -- \"%s\"",
1289 acutest_argv0_, index, acutest_timer_ ? "--time" : "",
1290 acutest_tap_ ? "--tap" : "", acutest_verbose_level_,
1291 acutest_colorize_ ? "always" : "never", test->name);
1292 memset(&startupInfo, 0, sizeof(startupInfo));
1293 startupInfo.cb = sizeof(STARTUPINFO);
1294 if (CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0, NULL, NULL,
1295 &startupInfo, &processInfo)) {
1296 WaitForSingleObject(processInfo.hProcess, INFINITE);
1297 GetExitCodeProcess(processInfo.hProcess, &exitCode);
1298 CloseHandle(processInfo.hThread);
1299 CloseHandle(processInfo.hProcess);
1300 switch (exitCode) {
1301 case 0:
1302 state = ACUTEST_STATE_SUCCESS;
1303 break;
1304 case 1:
1305 state = ACUTEST_STATE_FAILED;
1306 break;
1307 case 2:
1308 state = ACUTEST_STATE_SKIPPED;
1309 break;
1310 case 3:
1311 acutest_error_("Aborted.");
1312 break;
1313 case 0xC0000005:
1314 acutest_error_("Access violation.");
1315 break;
1316 default:
1317 acutest_error_("Test ended in an unexpected way [%lu].", exitCode);
1318 break;
1319 }
1320 } else {
1321 acutest_error_("Cannot create unit test subprocess [%ld].",
1322 GetLastError());
1323 }
1324
1325# else
1326
1327 /* A platform where we don't know how to run child process. */
1328 state = acutest_do_run_(test, index);
1329
1330# endif
1331
1332 } else {
1333 /* Child processes suppressed through --no-exec. */
1334 state = acutest_do_run_(test, index);
1335 }
1337
1338 acutest_current_test_ = NULL;
1339
1340 acutest_test_data_[master_index].state = state;
1341 acutest_test_data_[master_index].duration = acutest_timer_diff_(start, end);
1342}
1343
1344# if defined(ACUTEST_WIN_)
1345/* Callback for SEH events. */
1346static LONG CALLBACK acutest_seh_exception_filter_(EXCEPTION_POINTERS *ptrs) {
1347 acutest_check_(0, NULL, 0, "Unhandled SEH exception");
1348 acutest_message_("Exception code: 0x%08lx",
1349 ptrs->ExceptionRecord->ExceptionCode);
1350 acutest_message_("Exception address: 0x%p",
1351 ptrs->ExceptionRecord->ExceptionAddress);
1352
1353 fflush(stdout);
1354 fflush(stderr);
1355
1356 return EXCEPTION_EXECUTE_HANDLER;
1357}
1358# endif
1359
1360# define ACUTEST_CMDLINE_OPTFLAG_OPTIONALARG_ 0x0001
1361# define ACUTEST_CMDLINE_OPTFLAG_REQUIREDARG_ 0x0002
1362
1363# define ACUTEST_CMDLINE_OPTID_NONE_ 0
1364# define ACUTEST_CMDLINE_OPTID_UNKNOWN_ (-0x7fffffff + 0)
1365# define ACUTEST_CMDLINE_OPTID_MISSINGARG_ (-0x7fffffff + 1)
1366# define ACUTEST_CMDLINE_OPTID_BOGUSARG_ (-0x7fffffff + 2)
1367
1374
1376 const ACUTEST_CMDLINE_OPTION_ *options, const char *arggroup,
1377 int (*callback)(int /*optval*/, const char * /*arg*/)) {
1378 const ACUTEST_CMDLINE_OPTION_ *opt;
1379 int i;
1380 int ret = 0;
1381
1382 for (i = 0; arggroup[i] != '\0'; i++) {
1383 for (opt = options; opt->id != 0; opt++) {
1384 if (arggroup[i] == opt->shortname)
1385 break;
1386 }
1387
1388 if (opt->id != 0 && !(opt->flags & ACUTEST_CMDLINE_OPTFLAG_REQUIREDARG_)) {
1389 ret = callback(opt->id, NULL);
1390 } else {
1391 /* Unknown option. */
1392 char badoptname[3];
1393 badoptname[0] = '-';
1394 badoptname[1] = arggroup[i];
1395 badoptname[2] = '\0';
1396 ret = callback((opt->id != 0 ? ACUTEST_CMDLINE_OPTID_MISSINGARG_
1398 badoptname);
1399 }
1400
1401 if (ret != 0)
1402 break;
1403 }
1404
1405 return ret;
1406}
1407
1408# define ACUTEST_CMDLINE_AUXBUF_SIZE_ 32
1409
1411 int argc, char **argv,
1412 int (*callback)(int /*optval*/,
1413 const char * /*arg*/)) {
1414
1415 const ACUTEST_CMDLINE_OPTION_ *opt;
1416 char auxbuf[ACUTEST_CMDLINE_AUXBUF_SIZE_ + 1];
1417 int after_doubledash = 0;
1418 int i = 1;
1419 int ret = 0;
1420
1421 auxbuf[ACUTEST_CMDLINE_AUXBUF_SIZE_] = '\0';
1422
1423 while (i < argc) {
1424 if (after_doubledash || strcmp(argv[i], "-") == 0) {
1425 /* Non-option argument. */
1426 ret = callback(ACUTEST_CMDLINE_OPTID_NONE_, argv[i]);
1427 } else if (strcmp(argv[i], "--") == 0) {
1428 /* End of options. All the remaining members are non-option arguments. */
1429 after_doubledash = 1;
1430 } else if (argv[i][0] != '-') {
1431 /* Non-option argument. */
1432 ret = callback(ACUTEST_CMDLINE_OPTID_NONE_, argv[i]);
1433 } else {
1434 for (opt = options; opt->id != 0; opt++) {
1435 if (opt->longname != NULL && strncmp(argv[i], "--", 2) == 0) {
1436 size_t len = strlen(opt->longname);
1437 if (strncmp(argv[i] + 2, opt->longname, len) == 0) {
1438 /* Regular long option. */
1439 if (argv[i][2 + len] == '\0') {
1440 /* with no argument provided. */
1442 ret = callback(opt->id, NULL);
1443 else
1444 ret = callback(ACUTEST_CMDLINE_OPTID_MISSINGARG_, argv[i]);
1445 break;
1446 } else if (argv[i][2 + len] == '=') {
1447 /* with an argument provided. */
1450 ret = callback(opt->id, argv[i] + 2 + len + 1);
1451 } else {
1452 snprintf(auxbuf, sizeof(auxbuf), "--%s", opt->longname);
1453 ret = callback(ACUTEST_CMDLINE_OPTID_BOGUSARG_, auxbuf);
1454 }
1455 break;
1456 } else {
1457 continue;
1458 }
1459 }
1460 } else if (opt->shortname != '\0' && argv[i][0] == '-') {
1461 if (argv[i][1] == opt->shortname) {
1462 /* Regular short option. */
1464 if (argv[i][2] != '\0')
1465 ret = callback(opt->id, argv[i] + 2);
1466 else if (i + 1 < argc)
1467 ret = callback(opt->id, argv[++i]);
1468 else
1469 ret = callback(ACUTEST_CMDLINE_OPTID_MISSINGARG_, argv[i]);
1470 break;
1471 } else {
1472 ret = callback(opt->id, NULL);
1473
1474 /* There might be more (argument-less) short options
1475 * grouped together. */
1476 if (ret == 0 && argv[i][2] != '\0')
1478 options, argv[i] + 2, callback);
1479 break;
1480 }
1481 }
1482 }
1483 }
1484
1485 if (opt->id == 0) { /* still not handled? */
1486 if (argv[i][0] != '-') {
1487 /* Non-option argument. */
1488 ret = callback(ACUTEST_CMDLINE_OPTID_NONE_, argv[i]);
1489 } else {
1490 /* Unknown option. */
1491 char *badoptname = argv[i];
1492
1493 if (strncmp(badoptname, "--", 2) == 0) {
1494 /* Strip any argument from the long option. */
1495 char *assignment = strchr(badoptname, '=');
1496 if (assignment != NULL) {
1497 size_t len = (size_t)(assignment - badoptname);
1500 strncpy(auxbuf, badoptname, len);
1501 auxbuf[len] = '\0';
1502 badoptname = auxbuf;
1503 }
1504 }
1505
1506 ret = callback(ACUTEST_CMDLINE_OPTID_UNKNOWN_, badoptname);
1507 }
1508 }
1509 }
1510
1511 if (ret != 0)
1512 return ret;
1513 i++;
1514 }
1515
1516 return ret;
1517}
1518
1519static void acutest_help_(void) {
1520 printf("Usage: %s [options] [test...]\n", acutest_argv0_);
1521 printf("\n");
1522 printf("Run the specified unit tests; or if the option '--exclude' is used, "
1523 "run all\n");
1524 printf("tests in the suite but those listed. By default, if no tests are "
1525 "specified\n");
1526 printf("on the command line, all unit tests in the suite are run.\n");
1527 printf("\n");
1528 printf("Options:\n");
1529 printf(
1530 " -X, --exclude Execute all unit tests but the listed ones\n");
1531 printf(" --exec[=WHEN] If supported, execute unit tests as child "
1532 "processes\n");
1533 printf(
1534 " (WHEN is one of 'auto', 'always', 'never')\n");
1535 printf(" -E, --no-exec Same as --exec=never\n");
1536# if defined ACUTEST_WIN_
1537 printf(" -t, --time Measure test duration\n");
1538# elif defined ACUTEST_HAS_POSIX_TIMER_
1539 printf(" -t, --time Measure test duration (real time)\n");
1540 printf(" --time=TIMER Measure test duration, using given timer\n");
1541 printf(" (TIMER is one of 'real', 'cpu')\n");
1542# endif
1543 printf(" --no-summary Suppress printing of test results summary\n");
1544 printf(" --tap Produce TAP-compliant output\n");
1545 printf(" (See https://testanything.org/)\n");
1546 printf(" -x, --xml-output=FILE Enable XUnit output to the given file\n");
1547 printf(" -l, --list List unit tests in the suite and exit\n");
1548 printf(" -v, --verbose Make output more verbose\n");
1549 printf(" --verbose=LEVEL Set verbose level to LEVEL:\n");
1550 printf(" 0 ... Be silent\n");
1551 printf(" 1 ... Output one line per test (and "
1552 "summary)\n");
1553 printf(" 2 ... As 1 and failed conditions (this is "
1554 "default)\n");
1555 printf(" 3 ... As 1 and all conditions (and "
1556 "extended summary)\n");
1557 printf(" -q, --quiet Same as --verbose=0\n");
1558 printf(" --color[=WHEN] Enable colorized output\n");
1559 printf(
1560 " (WHEN is one of 'auto', 'always', 'never')\n");
1561 printf(" --no-color Same as --color=never\n");
1562 printf(" -h, --help Display this help and exit\n");
1563
1564 if (acutest_list_size_ < 16) {
1565 printf("\n");
1567 }
1568}
1569
1571 {'X', "exclude", 'X', 0},
1572 {'s', "skip", 'X', 0}, /* kept for compatibility, use --exclude instead */
1573 {0, "exec", 'e', ACUTEST_CMDLINE_OPTFLAG_OPTIONALARG_},
1574 {'E', "no-exec", 'E', 0},
1575# if defined ACUTEST_WIN_
1576 {'t', "time", 't', 0},
1577 {0, "timer", 't', 0}, /* kept for compatibility */
1578# elif defined ACUTEST_HAS_POSIX_TIMER_
1579 {'t', "time", 't', ACUTEST_CMDLINE_OPTFLAG_OPTIONALARG_},
1580 {0, "timer", 't',
1581 ACUTEST_CMDLINE_OPTFLAG_OPTIONALARG_}, /* kept for compatibility */
1582# endif
1583 {0, "no-summary", 'S', 0},
1584 {0, "tap", 'T', 0},
1585 {'l', "list", 'l', 0},
1586 {'v', "verbose", 'v', ACUTEST_CMDLINE_OPTFLAG_OPTIONALARG_},
1587 {'q', "quiet", 'q', 0},
1588 {0, "color", 'c', ACUTEST_CMDLINE_OPTFLAG_OPTIONALARG_},
1589 {0, "no-color", 'C', 0},
1590 {'h', "help", 'h', 0},
1591 {0, "worker", 'w', ACUTEST_CMDLINE_OPTFLAG_REQUIREDARG_}, /* internal */
1592 {'x', "xml-output", 'x', ACUTEST_CMDLINE_OPTFLAG_REQUIREDARG_},
1593 {0, NULL, 0, 0}};
1594
1595static int acutest_cmdline_callback_(int id, const char *arg) {
1596 switch (id) {
1597 case 'X':
1599 break;
1600
1601 case 'e':
1602 if (arg == NULL || strcmp(arg, "always") == 0) {
1603 acutest_no_exec_ = 0;
1604 } else if (strcmp(arg, "never") == 0) {
1605 acutest_no_exec_ = 1;
1606 } else if (strcmp(arg, "auto") == 0) {
1607 /*noop*/
1608 } else {
1609 fprintf(stderr, "%s: Unrecognized argument '%s' for option --exec.\n",
1610 acutest_argv0_, arg);
1611 fprintf(stderr, "Try '%s --help' for more information.\n",
1613 acutest_exit_(2);
1614 }
1615 break;
1616
1617 case 'E':
1618 acutest_no_exec_ = 1;
1619 break;
1620
1621 case 't':
1622# if defined ACUTEST_WIN_ || defined ACUTEST_HAS_POSIX_TIMER_
1623 if (arg == NULL || strcmp(arg, "real") == 0) {
1624 acutest_timer_ = 1;
1625# ifndef ACUTEST_WIN_
1626 } else if (strcmp(arg, "cpu") == 0) {
1627 acutest_timer_ = 2;
1628# endif
1629 } else {
1630 fprintf(stderr, "%s: Unrecognized argument '%s' for option --time.\n",
1631 acutest_argv0_, arg);
1632 fprintf(stderr, "Try '%s --help' for more information.\n",
1634 acutest_exit_(2);
1635 }
1636# endif
1637 break;
1638
1639 case 'S':
1641 break;
1642
1643 case 'T':
1644 acutest_tap_ = 1;
1645 break;
1646
1647 case 'l':
1649 acutest_exit_(0);
1650 break;
1651
1652 case 'v':
1654 (arg != NULL ? atoi(arg) : acutest_verbose_level_ + 1);
1655 break;
1656
1657 case 'q':
1659 break;
1660
1661 case 'c':
1662 if (arg == NULL || strcmp(arg, "always") == 0) {
1664 } else if (strcmp(arg, "never") == 0) {
1666 } else if (strcmp(arg, "auto") == 0) {
1667 /*noop*/
1668 } else {
1669 fprintf(stderr, "%s: Unrecognized argument '%s' for option --color.\n",
1670 acutest_argv0_, arg);
1671 fprintf(stderr, "Try '%s --help' for more information.\n",
1673 acutest_exit_(2);
1674 }
1675 break;
1676
1677 case 'C':
1679 break;
1680
1681 case 'h':
1682 acutest_help_();
1683 acutest_exit_(0);
1684 break;
1685
1686 case 'w':
1687 acutest_worker_ = 1;
1688 acutest_worker_index_ = atoi(arg);
1689 break;
1690 case 'x':
1691 acutest_xml_output_ = fopen(arg, "w");
1692 if (!acutest_xml_output_) {
1693 fprintf(stderr, "Unable to open '%s': %s\n", arg, strerror(errno));
1694 acutest_exit_(2);
1695 }
1696 break;
1697
1698 case 0:
1699 if (acutest_select_(arg) == 0) {
1700 fprintf(stderr, "%s: Unrecognized unit test '%s'\n", acutest_argv0_, arg);
1701 fprintf(stderr, "Try '%s --list' for list of unit tests.\n",
1703 acutest_exit_(2);
1704 }
1705 break;
1706
1708 fprintf(stderr, "Unrecognized command line option '%s'.\n", arg);
1709 fprintf(stderr, "Try '%s --help' for more information.\n", acutest_argv0_);
1710 acutest_exit_(2);
1711 break;
1712
1714 fprintf(stderr, "The command line option '%s' requires an argument.\n",
1715 arg);
1716 fprintf(stderr, "Try '%s --help' for more information.\n", acutest_argv0_);
1717 acutest_exit_(2);
1718 break;
1719
1721 fprintf(stderr,
1722 "The command line option '%s' does not expect an argument.\n", arg);
1723 fprintf(stderr, "Try '%s --help' for more information.\n", acutest_argv0_);
1724 acutest_exit_(2);
1725 break;
1726 }
1727
1728 return 0;
1729}
1730
1731static int acutest_under_debugger_(void) {
1732# ifdef ACUTEST_LINUX_
1733 /* Scan /proc/self/status for line "TracerPid: [PID]". If such line exists
1734 * and the PID is non-zero, we're being debugged. */
1735 {
1736 static const int OVERLAP = 32;
1737 int fd;
1738 char buf[512];
1739 size_t n_read;
1740 pid_t tracer_pid = 0;
1741
1742 /* Little trick so that we can treat the 1st line the same as any other
1743 * and detect line start easily. */
1744 buf[0] = '\n';
1745 n_read = 1;
1746
1747 fd = open("/proc/self/status", O_RDONLY);
1748 if (fd != -1) {
1749 while (1) {
1750 static const char pattern[] = "\nTracerPid:";
1751 const char *field;
1752
1753 while (n_read < sizeof(buf) - 1) {
1754 ssize_t n;
1755
1756 n = read(fd, buf + n_read, sizeof(buf) - 1 - n_read);
1757 if (n <= 0)
1758 break;
1759 n_read += (size_t)n;
1760 }
1761 buf[n_read] = '\0';
1762
1763 field = strstr(buf, pattern);
1764 if (field != NULL && field < buf + sizeof(buf) - OVERLAP) {
1765 tracer_pid = (pid_t)atoi(field + sizeof(pattern) - 1);
1766 break;
1767 }
1768
1769 if (n_read == sizeof(buf) - 1) {
1770 /* Move the tail with the potentially incomplete line we're
1771 * be looking for to the beginning of the buffer.
1772 * (The OVERLAP must be large enough so the searched line
1773 * can fit in completely.) */
1774 memmove(buf, buf + sizeof(buf) - 1 - OVERLAP, OVERLAP);
1775 n_read = OVERLAP;
1776 } else {
1777 break;
1778 }
1779 }
1780
1781 close(fd);
1782
1783 if (tracer_pid != 0)
1784 return 1;
1785 }
1786 }
1787# endif
1788
1789# ifdef ACUTEST_MACOS_
1790 /* See https://developer.apple.com/library/archive/qa/qa1361/_index.html */
1791 {
1792 int mib[4];
1793 struct kinfo_proc info;
1794 size_t size;
1795
1796 mib[0] = CTL_KERN;
1797 mib[1] = KERN_PROC;
1798 mib[2] = KERN_PROC_PID;
1799 mib[3] = getpid();
1800
1801 size = sizeof(info);
1802 info.kp_proc.p_flag = 0;
1803 sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, NULL, 0);
1804
1805 if (info.kp_proc.p_flag & P_TRACED)
1806 return 1;
1807 }
1808# endif
1809
1810# ifdef ACUTEST_WIN_
1811 if (IsDebuggerPresent())
1812 return 1;
1813# endif
1814
1815# ifdef RUNNING_ON_VALGRIND
1816 /* We treat Valgrind as a debugger of sorts.
1817 * (Macro RUNNING_ON_VALGRIND is provided by <valgrind.h>, if available.) */
1818 if (RUNNING_ON_VALGRIND)
1819 return 1;
1820# endif
1821
1822 return 0;
1823}
1824
1825int main(int argc, char **argv) {
1826 int i, index;
1827 int exit_code = 1;
1828
1829 acutest_argv0_ = argv[0];
1830
1831# if defined ACUTEST_UNIX_
1832 acutest_colorize_ = isatty(STDOUT_FILENO);
1833# elif defined ACUTEST_WIN_
1834# if defined _BORLANDC_
1835 acutest_colorize_ = isatty(_fileno(stdout));
1836# else
1837 acutest_colorize_ = _isatty(_fileno(stdout));
1838# endif
1839# else
1841# endif
1842
1843 /* Count all test units */
1845 for (i = 0; acutest_list_[i].func != NULL; i++)
1847
1848 acutest_test_data_ = (struct acutest_test_data_ *)calloc(
1849 acutest_list_size_, sizeof(struct acutest_test_data_));
1850 if (acutest_test_data_ == NULL) {
1851 fprintf(stderr, "Out of memory.\n");
1852 acutest_exit_(2);
1853 }
1854
1855 /* Parse options */
1858
1859 /* Initialize the proper timer. */
1861
1862# if defined(ACUTEST_WIN_)
1863 SetUnhandledExceptionFilter(acutest_seh_exception_filter_);
1864# ifdef _MSC_VER
1865 _set_abort_behavior(0, _WRITE_ABORT_MSG);
1866# endif
1867# endif
1868
1869 /* Determine what to run. */
1871 enum acutest_state_ if_selected;
1872 enum acutest_state_ if_unselected;
1873
1874 if (!acutest_exclude_mode_) {
1875 if_selected = ACUTEST_STATE_NEEDTORUN;
1876 if_unselected = ACUTEST_STATE_EXCLUDED;
1877 } else {
1878 if_selected = ACUTEST_STATE_EXCLUDED;
1879 if_unselected = ACUTEST_STATE_NEEDTORUN;
1880 }
1881
1882 for (i = 0; acutest_list_[i].func != NULL; i++) {
1884 acutest_test_data_[i].state = if_selected;
1885 else
1886 acutest_test_data_[i].state = if_unselected;
1887 }
1888 } else {
1889 /* By default, we want to run all tests. */
1890 for (i = 0; acutest_list_[i].func != NULL; i++)
1892 }
1893
1894 /* By default, we want to suppress running tests as child processes if we
1895 * run just one test, or if we're under debugger: Debugging tests is then
1896 * so much easier. */
1897 if (acutest_no_exec_ < 0) {
1900 acutest_no_exec_ = 1;
1901 else
1902 acutest_no_exec_ = 0;
1903 }
1904
1905 if (acutest_tap_) {
1906 /* TAP requires we know test result ("ok", "not ok") before we output
1907 * anything about the test, and this gets problematic for larger verbose
1908 * levels. */
1909 if (acutest_verbose_level_ > 2)
1911
1912 /* TAP harness should provide some summary. */
1914
1915 if (!acutest_worker_)
1916 printf("1..%d\n", acutest_count_(ACUTEST_STATE_NEEDTORUN));
1917 }
1918
1919 index = acutest_worker_index_;
1920 for (i = 0; acutest_list_[i].func != NULL; i++) {
1922 acutest_run_(&acutest_list_[i], index++, i);
1923 }
1924
1925 /* Write a summary */
1927 int n_run, n_success, n_failed;
1928
1932
1933 if (acutest_verbose_level_ >= 3) {
1934 acutest_colored_printf_(ACUTEST_COLOR_DEFAULT_INTENSIVE_, "Summary:\n");
1935
1936 printf(" Count of run unit tests: %4d\n", n_run);
1937 printf(" Count of successful unit tests: %4d\n", n_success);
1938 printf(" Count of failed unit tests: %4d\n", n_failed);
1939 }
1940
1941 if (n_failed == 0) {
1942 acutest_colored_printf_(ACUTEST_COLOR_GREEN_INTENSIVE_, "SUCCESS:");
1943 printf(" No unit tests have failed.\n");
1944 } else {
1945 acutest_colored_printf_(ACUTEST_COLOR_RED_INTENSIVE_, "FAILED:");
1946 printf(" %d of %d unit tests %s failed.\n", n_failed, n_run,
1947 (n_failed == 1) ? "has" : "have");
1948 }
1949
1950 if (acutest_verbose_level_ >= 3)
1951 printf("\n");
1952 }
1953
1954 if (acutest_xml_output_) {
1955 const char *suite_name = acutest_basename_(argv[0]);
1956 fprintf(acutest_xml_output_,
1957 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
1958 fprintf(acutest_xml_output_,
1959 "<testsuite name=\"%s\" tests=\"%d\" errors=\"0\" failures=\"%d\" "
1960 "skip=\"%d\">\n",
1961 suite_name, (int)acutest_list_size_,
1965 for (i = 0; acutest_list_[i].func != NULL; i++) {
1966 struct acutest_test_data_ *details = &acutest_test_data_[i];
1967 const char *str_state;
1968 fprintf(acutest_xml_output_, " <testcase name=\"%s\" time=\"%.2f\">\n",
1969 acutest_list_[i].name, details->duration);
1970
1971 switch (details->state) {
1973 str_state = NULL;
1974 break;
1975 case ACUTEST_STATE_EXCLUDED: /* Fall through. */
1977 str_state = "<skipped />";
1978 break;
1979 case ACUTEST_STATE_FAILED: /* Fall through. */
1980 default:
1981 str_state = "<failure />";
1982 break;
1983 }
1984
1985 if (str_state != NULL)
1986 fprintf(acutest_xml_output_, " %s\n", str_state);
1987 fprintf(acutest_xml_output_, " </testcase>\n");
1988 }
1989 fprintf(acutest_xml_output_, "</testsuite>\n");
1990 fclose(acutest_xml_output_);
1991 }
1992
1993 if (acutest_worker_ &&
1995 /* If we are the child process, we need to propagate the test state
1996 * without any moderation. */
1997 for (i = 0; acutest_list_[i].func != NULL; i++) {
1999 exit_code = (int)acutest_test_data_[i].state;
2000 break;
2001 }
2002 }
2003 } else {
2005 exit_code = 1;
2006 else
2007 exit_code = 0;
2008 }
2009
2011 return exit_code;
2012}
2013
2014#endif /* #ifndef TEST_NO_MAIN */
2015
2016#ifdef _MSC_VER
2017# pragma warning(pop)
2018#endif
2019
2020#ifdef __cplusplus
2021} /* extern "C" */
2022#endif
2023
2024#endif /* #ifndef ACUTEST_H */
int main(void)
Definition 01_hello.c:45
#define ACUTEST_CMDLINE_OPTID_NONE_
Definition acutest.h:1363
#define ACUTEST_ATTRIBUTE_(attr)
Definition acutest.h:297
vsnprintf(buffer, sizeof(buffer), fmt, args)
static void acutest_init_(const char *test_name)
Definition acutest.h:968
struct acutest_test_CMDLINE_OPTION_ ACUTEST_CMDLINE_OPTION_
static int acutest_test_failures_
Definition acutest.h:432
static int const char * fmt
Definition acutest.h:535
#define ACUTEST_COLOR_DEFAULT_INTENSIVE_
Definition acutest.h:529
static const ACUTEST_CMDLINE_OPTION_ acutest_cmdline_options_[]
Definition acutest.h:1570
static void acutest_line_indent_(int level)
Definition acutest.h:726
#define ACUTEST_COLOR_GREEN_INTENSIVE_
Definition acutest.h:531
static int acutest_name_contains_word_(const char *name, const char *pattern)
Definition acutest.h:1007
static int acutest_test_already_logged_
Definition acutest.h:429
static int acutest_no_exec_
Definition acutest.h:414
static void acutest_finish_test_line_(enum acutest_state_ state)
Definition acutest.h:679
void acutest_dump_(const char *title, const void *addr, size_t size)
Definition acutest.h:915
#define TEST_MSG_MAXSIZE
Definition acutest.h:232
static FILE * acutest_xml_output_
Definition acutest.h:421
int acutest_check_(int cond, const char *file, int line, const char *fmt,...)
int const char * file
Definition acutest.h:788
acutest_state_
Definition acutest.h:304
@ ACUTEST_STATE_SKIPPED
Definition acutest.h:313
@ ACUTEST_STATE_FAILED
Definition acutest.h:312
@ ACUTEST_STATE_SUCCESS
Definition acutest.h:311
@ ACUTEST_STATE_SELECTED
Definition acutest.h:306
@ ACUTEST_STATE_INITIAL
Definition acutest.h:305
@ ACUTEST_STATE_NEEDTORUN
Definition acutest.h:307
@ ACUTEST_STATE_EXCLUDED
Definition acutest.h:310
static int acutest_worker_
Definition acutest.h:418
static int acutest_colorize_
Definition acutest.h:433
static char acutest_case_name_[TEST_CASE_MAXSIZE]
Definition acutest.h:425
int acutest_timer_type_
Definition acutest.h:508
static void acutest_cleanup_(void)
Definition acutest.h:450
va_end(args)
int verbose_level
Definition acutest.h:791
static void acutest_timer_print_diff_(void)
Definition acutest.h:522
#define ACUTEST_COLOR_GREEN_
Definition acutest.h:527
static int acutest_case_already_logged_
Definition acutest.h:430
int n
Definition acutest.h:538
static int const char char buffer[256]
Definition acutest.h:537
static const struct acutest_test_ * acutest_current_test_
Definition acutest.h:423
#define TEST_CASE_MAXSIZE
Definition acutest.h:202
static int acutest_list_size_
Definition acutest.h:412
static void acutest_help_(void)
Definition acutest.h:1519
static int acutest_cond_failed_
Definition acutest.h:420
static int acutest_timer_
Definition acutest.h:434
#define ACUTEST_CMDLINE_OPTID_MISSINGARG_
Definition acutest.h:1365
static void acutest_fini_(const char *test_name)
Definition acutest.h:978
static void acutest_timer_get_time_(int *ts)
Definition acutest.h:514
#define ACUTEST_CMDLINE_OPTID_UNKNOWN_
Definition acutest.h:1364
#define ACUTEST_CMDLINE_OPTID_BOGUSARG_
Definition acutest.h:1366
static void acutest_list_names_(void)
Definition acutest.h:999
static int acutest_cmdline_read_(const ACUTEST_CMDLINE_OPTION_ *options, int argc, char **argv, int(*callback)(int, const char *))
Definition acutest.h:1410
static void acutest_run_(const struct acutest_test_ *test, int index, int master_index)
Definition acutest.h:1205
static int acutest_verbose_level_
Definition acutest.h:431
const struct acutest_test_ acutest_list_[]
static int acutest_cmdline_handle_short_opt_group_(const ACUTEST_CMDLINE_OPTION_ *options, const char *arggroup, int(*callback)(int, const char *))
Definition acutest.h:1375
void acutest_timer_init_(void)
Definition acutest.h:512
#define ACUTEST_CMDLINE_AUXBUF_SIZE_
Definition acutest.h:1408
static int acutest_abort_has_jmp_buf_
Definition acutest.h:436
static void acutest_begin_test_line_(const struct acutest_test_ *test)
Definition acutest.h:658
void char * line_beg
Definition acutest.h:883
char * line_end
Definition acutest.h:884
static int acutest_test_skip_count_
Definition acutest.h:427
va_list args
Definition acutest.h:885
int const char int const char int result_color
Definition acutest.h:790
static char acutest_test_skip_reason_[256]
Definition acutest.h:428
static int acutest_under_debugger_(void)
Definition acutest.h:1731
static double acutest_timer_diff_(int start, int end)
Definition acutest.h:516
void acutest_abort_(void) ACUTEST_ATTRIBUTE_(noreturn)
Definition acutest.h:987
static int acutest_count_(enum acutest_state_ state)
Definition acutest.h:439
static enum acutest_state_ acutest_do_run_(const struct acutest_test_ *test, int index)
Definition acutest.h:1093
#define ACUTEST_CMDLINE_OPTFLAG_REQUIREDARG_
Definition acutest.h:1361
static int acutest_worker_index_
Definition acutest.h:419
static int acutest_cmdline_callback_(int id, const char *arg)
Definition acutest.h:1595
#define ACUTEST_COLOR_YELLOW_
Definition acutest.h:528
static jmp_buf acutest_abort_jmp_buf_
Definition acutest.h:437
#define ACUTEST_COLOR_RED_INTENSIVE_
Definition acutest.h:530
static int acutest_test_check_count_
Definition acutest.h:426
void int const char size_t reason_len
Definition acutest.h:745
static int acutest_select_(const char *pattern)
Definition acutest.h:1031
result_str
Definition acutest.h:812
void int line
Definition acutest.h:743
static int acutest_tap_
Definition acutest.h:416
#define ACUTEST_COLOR_RED_
Definition acutest.h:526
#define TEST_DUMP_MAXSIZE
Definition acutest.h:252
static acutest_timer_type_ acutest_timer_start_
Definition acutest.h:509
va_start(args, fmt)
static int acutest_current_index_
Definition acutest.h:424
static int acutest_no_summary_
Definition acutest.h:415
static char * acutest_argv0_
Definition acutest.h:411
static acutest_timer_type_ acutest_timer_end_
Definition acutest.h:510
#define ACUTEST_CMDLINE_OPTFLAG_OPTIONALARG_
Definition acutest.h:1360
void acutest_case_(const char *fmt,...)
static const char * acutest_basename_(const char *path)
Definition acutest.h:631
void acutest_message_(const char *fmt,...)
#define ACUTEST_COLOR_YELLOW_INTENSIVE_
Definition acutest.h:532
static int acutest_exclude_mode_
Definition acutest.h:417
const char * name
Definition acutest.h:400
void(* func)(void)
Definition acutest.h:401
enum acutest_state_ state
Definition acutest.h:405