xref: /freebsd/contrib/expat/tests/minicheck.h (revision 207d96dabfec14d7b3699747abb539ab3c1118ab)
1 /* Miniature re-implementation of the "check" library.
2 
3    This is intended to support just enough of check to run the Expat
4    tests.  This interface is based entirely on the portion of the
5    check library being used.
6 
7    This is *source* compatible, but not necessary *link* compatible.
8                             __  __            _
9                          ___\ \/ /_ __   __ _| |_
10                         / _ \\  /| '_ \ / _` | __|
11                        |  __//  \| |_) | (_| | |_
12                         \___/_/\_\ .__/ \__,_|\__|
13                                  |_| XML parser
14 
15    Copyright (c) 2004-2006 Fred L. Drake, Jr. <fdrake@users.sourceforge.net>
16    Copyright (c) 2006-2012 Karl Waclawek <karl@waclawek.net>
17    Copyright (c) 2016-2025 Sebastian Pipping <sebastian@pipping.org>
18    Copyright (c) 2022      Rhodri James <rhodri@wildebeest.org.uk>
19    Copyright (c) 2023-2024 Sony Corporation / Snild Dolkow <snild@sony.com>
20    Licensed under the MIT license:
21 
22    Permission is  hereby granted,  free of charge,  to any  person obtaining
23    a  copy  of  this  software   and  associated  documentation  files  (the
24    "Software"),  to  deal in  the  Software  without restriction,  including
25    without  limitation the  rights  to use,  copy,  modify, merge,  publish,
26    distribute, sublicense, and/or sell copies of the Software, and to permit
27    persons  to whom  the Software  is  furnished to  do so,  subject to  the
28    following conditions:
29 
30    The above copyright  notice and this permission notice  shall be included
31    in all copies or substantial portions of the Software.
32 
33    THE  SOFTWARE  IS  PROVIDED  "AS  IS",  WITHOUT  WARRANTY  OF  ANY  KIND,
34    EXPRESS  OR IMPLIED,  INCLUDING  BUT  NOT LIMITED  TO  THE WARRANTIES  OF
35    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
36    NO EVENT SHALL THE AUTHORS OR  COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
37    DAMAGES OR  OTHER LIABILITY, WHETHER  IN AN  ACTION OF CONTRACT,  TORT OR
38    OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
39    USE OR OTHER DEALINGS IN THE SOFTWARE.
40 
41    SPDX-License-Identifier: MIT
42 */
43 
44 #ifdef __cplusplus
45 extern "C" {
46 #endif
47 
48 #ifndef XML_MINICHECK_H
49 #  define XML_MINICHECK_H
50 
51 #  define CK_NOFORK 0
52 #  define CK_FORK 1
53 
54 #  define CK_SILENT 0
55 #  define CK_NORMAL 1
56 #  define CK_VERBOSE 2
57 
58 /* Workaround for Microsoft's compiler and Tru64 Unix systems where the
59    C compiler has a working __func__, but the C++ compiler only has a
60    working __FUNCTION__.  This could be fixed in configure.in, but it's
61    not worth it right now. */
62 #  if defined(_MSC_VER) || (defined(__osf__) && defined(__cplusplus))
63 #    define __func__ __FUNCTION__
64 #  endif
65 
66 /* PRINTF_LIKE has two effects:
67     1. Make clang's -Wformat-nonliteral stop warning about non-literal format
68        strings in annotated functions' code.
69     2. Make both clang and gcc's -Wformat-nonliteral warn about *callers* of
70        the annotated function that use a non-literal format string.
71 */
72 #  if defined(__GNUC__)
73 #    define PRINTF_LIKE(fmtpos, argspos)                                       \
74       __attribute__((format(printf, fmtpos, argspos)))
75 #  else
76 #    define PRINTF_LIKE(fmtpos, argspos)
77 #  endif
78 
79 #  define START_TEST(testname)                                                 \
80     static void testname(void) {                                               \
81       _check_set_test_info(__func__, __FILE__, __LINE__);                      \
82       {
83 #  define END_TEST                                                             \
84     }                                                                          \
85     }
86 
87 void PRINTF_LIKE(1, 2) set_subtest(char const *fmt, ...);
88 
89 #  define fail(msg) _fail(__FILE__, __LINE__, msg)
90 #  define assert_true(cond)                                                    \
91     do {                                                                       \
92       if (! (cond)) {                                                          \
93         _fail(__FILE__, __LINE__, "check failed: " #cond);                     \
94       }                                                                        \
95     } while (0)
96 
97 typedef void (*tcase_setup_function)(void);
98 typedef void (*tcase_teardown_function)(void);
99 typedef void (*tcase_test_function)(void);
100 
101 typedef struct SRunner SRunner;
102 typedef struct Suite Suite;
103 typedef struct TCase TCase;
104 
105 struct SRunner {
106   Suite *suite;
107   int nchecks;
108   int nfailures;
109 };
110 
111 struct Suite {
112   const char *name;
113   TCase *tests;
114 };
115 
116 struct TCase {
117   const char *name;
118   tcase_setup_function setup;
119   tcase_teardown_function teardown;
120   tcase_test_function *tests;
121   int ntests;
122   int allocated;
123   TCase *next_tcase;
124 };
125 
126 /* Internal helper. */
127 void _check_set_test_info(char const *function, char const *filename,
128                           int lineno);
129 
130 /*
131  * Prototypes for the actual implementation.
132  */
133 
134 #  if defined(__has_attribute)
135 #    if __has_attribute(noreturn)
136 __attribute__((noreturn))
137 #    endif
138 #  endif
139 void _fail(const char *file, int line, const char *msg);
140 Suite *suite_create(const char *name);
141 TCase *tcase_create(const char *name);
142 void suite_add_tcase(Suite *suite, TCase *tc);
143 void tcase_add_checked_fixture(TCase *tc, tcase_setup_function setup,
144                                tcase_teardown_function teardown);
145 void tcase_add_test(TCase *tc, tcase_test_function test);
146 SRunner *srunner_create(Suite *suite);
147 void srunner_run_all(SRunner *runner, const char *context, int verbosity);
148 void srunner_summarize(SRunner *runner, int verbosity);
149 int srunner_ntests_failed(SRunner *runner);
150 void srunner_free(SRunner *runner);
151 
152 #endif /* XML_MINICHECK_H */
153 
154 #ifdef __cplusplus
155 }
156 #endif
157