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