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