Apache HTTPD
minicheck.c
Go to the documentation of this file.
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 ___\ \/ /_ __ __ _| |_
8 / _ \\ /| '_ \ / _` | __|
9 | __// \| |_) | (_| | |_
10 \___/_/\_\ .__/ \__,_|\__|
11 |_| XML parser
12
13 Copyright (c) 2004-2006 Fred L. Drake, Jr. <[email protected]>
14 Copyright (c) 2016-2023 Sebastian Pipping <[email protected]>
15 Copyright (c) 2017 Rhodri James <[email protected]>
16 Copyright (c) 2018 Marco Maggi <[email protected]>
17 Copyright (c) 2019 David Loffredo <[email protected]>
18 Copyright (c) 2023-2024 Sony Corporation / Snild Dolkow <[email protected]>
19 Licensed under the MIT license:
20
21 Permission is hereby granted, free of charge, to any person obtaining
22 a copy of this software and associated documentation files (the
23 "Software"), to deal in the Software without restriction, including
24 without limitation the rights to use, copy, modify, merge, publish,
25 distribute, sublicense, and/or sell copies of the Software, and to permit
26 persons to whom the Software is furnished to do so, subject to the
27 following conditions:
28
29 The above copyright notice and this permission notice shall be included
30 in all copies or substantial portions of the Software.
31
32 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
33 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
34 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
35 NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
36 DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
37 OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
38 USE OR OTHER DEALINGS IN THE SOFTWARE.
39*/
40
41#if defined(NDEBUG)
42# undef NDEBUG /* because test suite relies on assert(...) at the moment */
43#endif
44
45#include <stdarg.h>
46#include <stdio.h>
47#include <stdlib.h>
48#include <setjmp.h>
49#include <assert.h>
50#include <string.h>
51
52#include "internal.h" /* for UNUSED_P only */
53#include "minicheck.h"
54
55Suite *
56suite_create(const char *name) {
57 Suite *suite = (Suite *)calloc(1, sizeof(Suite));
58 if (suite != NULL) {
59 suite->name = name;
60 }
61 return suite;
62}
63
64TCase *
65tcase_create(const char *name) {
66 TCase *tc = (TCase *)calloc(1, sizeof(TCase));
67 if (tc != NULL) {
68 tc->name = name;
69 }
70 return tc;
71}
72
73void
75 assert(suite != NULL);
76 assert(tc != NULL);
77 assert(tc->next_tcase == NULL);
78
79 tc->next_tcase = suite->tests;
80 suite->tests = tc;
81}
82
83void
85 tcase_teardown_function teardown) {
86 assert(tc != NULL);
87 tc->setup = setup;
88 tc->teardown = teardown;
89}
90
91void
93 assert(tc != NULL);
94 if (tc->allocated == tc->ntests) {
95 int nalloc = tc->allocated + 100;
96 size_t new_size = sizeof(tcase_test_function) * nalloc;
100 tc->tests = new_tests;
101 tc->allocated = nalloc;
102 }
103 tc->tests[tc->ntests] = test;
104 tc->ntests++;
105}
106
107static void
109 if (! tc) {
110 return;
111 }
112
113 free(tc->tests);
114 free(tc);
115}
116
117static void
119 if (! suite) {
120 return;
121 }
122
123 while (suite->tests != NULL) {
124 TCase *next = suite->tests->next_tcase;
125 tcase_free(suite->tests);
126 suite->tests = next;
127 }
128 free(suite);
129}
130
131SRunner *
133 SRunner *const runner = (SRunner *)calloc(1, sizeof(SRunner));
134 if (runner != NULL) {
135 runner->suite = suite;
136 }
137 return runner;
138}
139
141
142#define SUBTEST_LEN (50) // informative, but not too long
143static char const *_check_current_function = NULL;
145static int _check_current_lineno = -1;
146static char const *_check_current_filename = NULL;
147
148void
149_check_set_test_info(char const *function, char const *filename, int lineno) {
150 _check_current_function = function;
151 set_subtest("%s", "");
152 _check_current_lineno = lineno;
154}
155
156void
157set_subtest(char const *fmt, ...) {
158 va_list ap;
159 va_start(ap, fmt);
161 va_end(ap);
162 // replace line feeds with spaces, for nicer error logs
163 for (size_t i = 0; i < SUBTEST_LEN; ++i) {
164 if (_check_current_subtest[i] == '\n') {
166 }
167 }
168 _check_current_subtest[SUBTEST_LEN - 1] = '\0'; // ensure termination
169}
170
171static void
173 if (verbosity >= CK_VERBOSE) {
174 printf("PASS: %s\n", _check_current_function);
175 }
176}
177
178static void
180 const char *phase_info) {
181 runner->nfailures++;
182 if (verbosity != CK_SILENT) {
183 if (strlen(_check_current_subtest) != 0) {
185 }
186 printf("FAIL [%s]: %s (%s at %s:%d)\n", context, _check_current_function,
188 }
189}
190
191void
193 Suite *suite;
194 TCase *volatile tc;
195 assert(runner != NULL);
196 suite = runner->suite;
197 tc = suite->tests;
198 while (tc != NULL) {
199 volatile int i;
200 for (i = 0; i < tc->ntests; ++i) {
201 runner->nchecks++;
202 set_subtest("%s", "");
203
204 if (tc->setup != NULL) {
205 /* setup */
206 if (setjmp(env)) {
207 handle_failure(runner, verbosity, context, "during setup");
208 continue;
209 }
210 tc->setup();
211 }
212 /* test */
213 if (setjmp(env)) {
214 handle_failure(runner, verbosity, context, "during actual test");
215 continue;
216 }
217 (tc->tests[i])();
218 set_subtest("%s", "");
219
220 /* teardown */
221 if (tc->teardown != NULL) {
222 if (setjmp(env)) {
223 handle_failure(runner, verbosity, context, "during teardown");
224 continue;
225 }
226 tc->teardown();
227 }
228
230 }
231 tc = tc->next_tcase;
232 }
233}
234
235void
237 if (verbosity != CK_SILENT) {
238 int passed = runner->nchecks - runner->nfailures;
239 double percentage = ((double)passed) / runner->nchecks;
240 int display = (int)(percentage * 100);
241 printf("%d%%: Checks: %d, Failed: %d\n", display, runner->nchecks,
242 runner->nfailures);
243 }
244}
245
246void
247_fail(const char *file, int line, const char *msg) {
248 /* Always print the error message so it isn't lost. In this case,
249 we have a failure, so there's no reason to be quiet about what
250 it is.
251 */
254 if (msg != NULL) {
255 const int has_newline = (msg[strlen(msg) - 1] == '\n');
256 fprintf(stderr, "ERROR: %s%s", msg, has_newline ? "" : "\n");
257 }
258 longjmp(env, 1);
259}
260
261int
263 assert(runner != NULL);
264 return runner->nfailures;
265}
266
267void
269 if (! runner) {
270 return;
271 }
272
273 suite_free(runner->suite);
274 free(runner);
275}
apr_md5_ctx_t * context
Definition util_md5.h:58
apr_size_t size
const char apr_file_t * file
apr_vformatter_buff_t const char * fmt
Definition apr_lib.h:175
apr_vformatter_buff_t const char va_list ap
Definition apr_lib.h:176
apr_size_t const char * filename
Definition apr_shm.h:72
static void suite_free(Suite *suite)
Definition minicheck.c:118
void tcase_add_test(TCase *tc, tcase_test_function test)
Definition minicheck.c:92
Suite * suite_create(const char *name)
Definition minicheck.c:56
void srunner_summarize(SRunner *runner, int verbosity)
Definition minicheck.c:236
static int _check_current_lineno
Definition minicheck.c:145
static char _check_current_subtest[(50)]
Definition minicheck.c:144
void _check_set_test_info(char const *function, char const *filename, int lineno)
Definition minicheck.c:149
static char const * _check_current_filename
Definition minicheck.c:146
void _fail(const char *file, int line, const char *msg)
Definition minicheck.c:247
void suite_add_tcase(Suite *suite, TCase *tc)
Definition minicheck.c:74
static void handle_success(int verbosity)
Definition minicheck.c:172
void srunner_run_all(SRunner *runner, const char *context, int verbosity)
Definition minicheck.c:192
SRunner * srunner_create(Suite *suite)
Definition minicheck.c:132
static void handle_failure(SRunner *runner, int verbosity, const char *context, const char *phase_info)
Definition minicheck.c:179
void set_subtest(char const *fmt,...)
Definition minicheck.c:157
static char const * _check_current_function
Definition minicheck.c:143
#define SUBTEST_LEN
Definition minicheck.c:142
void tcase_add_checked_fixture(TCase *tc, tcase_setup_function setup, tcase_teardown_function teardown)
Definition minicheck.c:84
int srunner_ntests_failed(SRunner *runner)
Definition minicheck.c:262
void srunner_free(SRunner *runner)
Definition minicheck.c:268
static void tcase_free(TCase *tc)
Definition minicheck.c:108
static jmp_buf env
Definition minicheck.c:140
TCase * tcase_create(const char *name)
Definition minicheck.c:65
void(* tcase_test_function)(void)
Definition minicheck.h:97
#define CK_VERBOSE
Definition minicheck.h:54
#define CK_SILENT
Definition minicheck.h:52
void(* tcase_teardown_function)(void)
Definition minicheck.h:96
void(* tcase_setup_function)(void)
Definition minicheck.h:95
return NULL
Definition mod_so.c:359
int i
Definition mod_so.c:347
char * name
Suite * suite
Definition minicheck.h:104
TCase * tests
Definition minicheck.h:111
const char * name
Definition minicheck.h:110
tcase_test_function * tests
Definition minicheck.h:118
const char * name
Definition minicheck.h:115
TCase * next_tcase
Definition minicheck.h:121
int ntests
Definition minicheck.h:119
int allocated
Definition minicheck.h:120
tcase_setup_function setup
Definition minicheck.h:116
tcase_teardown_function teardown
Definition minicheck.h:117
typedef int(WSAAPI *apr_winapi_fpt_WSAPoll)(IN OUT LPWSAPOLLFD fdArray