diff options
Diffstat (limited to '')
-rw-r--r-- | src/regress/lib/libcrypto/test/test.c | 226 |
1 files changed, 226 insertions, 0 deletions
diff --git a/src/regress/lib/libcrypto/test/test.c b/src/regress/lib/libcrypto/test/test.c new file mode 100644 index 0000000000..1188ec34ef --- /dev/null +++ b/src/regress/lib/libcrypto/test/test.c | |||
@@ -0,0 +1,226 @@ | |||
1 | /* $OpenBSD: test.c,v 1.4 2025/05/31 11:36:48 tb Exp $ */ | ||
2 | /* | ||
3 | * Copyright (c) 2025 Joshua Sing <joshua@joshuasing.dev> | ||
4 | * | ||
5 | * Permission to use, copy, modify, and distribute this software for any | ||
6 | * purpose with or without fee is hereby granted, provided that the above | ||
7 | * copyright notice and this permission notice appear in all copies. | ||
8 | * | ||
9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
16 | */ | ||
17 | |||
18 | #include <err.h> | ||
19 | #include <stdarg.h> | ||
20 | #include <stdio.h> | ||
21 | #include <stdlib.h> | ||
22 | #include <string.h> | ||
23 | #include <unistd.h> | ||
24 | |||
25 | #include "test.h" | ||
26 | |||
27 | struct test { | ||
28 | struct test *parent; | ||
29 | char *name; | ||
30 | FILE *out; | ||
31 | int skipped; | ||
32 | int failed; | ||
33 | }; | ||
34 | |||
35 | static struct test * | ||
36 | test_new(struct test *pt, const char *name) | ||
37 | { | ||
38 | struct test *t; | ||
39 | |||
40 | if ((t = calloc(1, sizeof(*t))) == NULL) | ||
41 | err(1, "calloc"); | ||
42 | |||
43 | if (name != NULL) { | ||
44 | if ((t->name = strdup(name)) == NULL) | ||
45 | err(1, "strdup"); | ||
46 | } | ||
47 | |||
48 | if (pt != NULL) | ||
49 | t->out = pt->out; | ||
50 | t->parent = pt; | ||
51 | |||
52 | return t; | ||
53 | } | ||
54 | |||
55 | struct test * | ||
56 | test_init(void) | ||
57 | { | ||
58 | struct test *t; | ||
59 | char *tmp_file; | ||
60 | int out_fd; | ||
61 | char *v; | ||
62 | |||
63 | t = test_new(NULL, NULL); | ||
64 | t->out = stderr; | ||
65 | |||
66 | if (((v = getenv("TEST_VERBOSE")) != NULL) && strcmp(v, "0") != 0) | ||
67 | return t; | ||
68 | |||
69 | /* Create a temporary file for logging in non-verbose mode */ | ||
70 | if ((tmp_file = strdup("/tmp/libressl-test.XXXXXXXX")) == NULL) | ||
71 | err(1, "strdup"); | ||
72 | if ((out_fd = mkstemp(tmp_file)) == -1) | ||
73 | err(1, "mkstemp"); | ||
74 | |||
75 | unlink(tmp_file); | ||
76 | free(tmp_file); | ||
77 | if ((t->out = fdopen(out_fd, "w+")) == NULL) | ||
78 | err(1, "fdopen"); | ||
79 | |||
80 | return t; | ||
81 | } | ||
82 | |||
83 | static void | ||
84 | test_cleanup(struct test *t) | ||
85 | { | ||
86 | free(t->name); | ||
87 | free(t); | ||
88 | } | ||
89 | |||
90 | int | ||
91 | test_result(struct test *t) | ||
92 | { | ||
93 | int failed = t->failed; | ||
94 | |||
95 | if (t->parent == NULL && t->out != stderr) | ||
96 | fclose(t->out); | ||
97 | |||
98 | test_cleanup(t); | ||
99 | |||
100 | return failed; | ||
101 | } | ||
102 | |||
103 | void | ||
104 | test_fail(struct test *t) | ||
105 | { | ||
106 | t->failed = 1; | ||
107 | |||
108 | /* Also fail parent. */ | ||
109 | if (t->parent != NULL) | ||
110 | test_fail(t->parent); | ||
111 | } | ||
112 | |||
113 | static void | ||
114 | test_vprintf(struct test *t, const char *fmt, va_list ap) | ||
115 | { | ||
116 | if (vfprintf(t->out, fmt, ap) == -1) | ||
117 | err(1, "vfprintf"); | ||
118 | } | ||
119 | |||
120 | void | ||
121 | test_printf(struct test *t, const char *fmt, ...) | ||
122 | { | ||
123 | va_list ap; | ||
124 | |||
125 | va_start(ap, fmt); | ||
126 | test_vprintf(t, fmt, ap); | ||
127 | va_end(ap); | ||
128 | } | ||
129 | |||
130 | static void | ||
131 | test_vlogf_internal(struct test *t, const char *label, const char *func, | ||
132 | const char *file, int line, const char *fmt, va_list ap) | ||
133 | { | ||
134 | char *msg = NULL; | ||
135 | char *l = ": "; | ||
136 | const char *filename; | ||
137 | |||
138 | if (label == NULL) { | ||
139 | label = ""; | ||
140 | l = ""; | ||
141 | } | ||
142 | |||
143 | if (vasprintf(&msg, fmt, ap) == -1) | ||
144 | err(1, "vasprintf"); | ||
145 | |||
146 | if ((filename = strrchr(file, '/')) != NULL) | ||
147 | filename++; | ||
148 | else | ||
149 | filename = file; | ||
150 | |||
151 | test_printf(t, "%s [%s:%d]%s%s: %s\n", | ||
152 | func, filename, line, l, label, msg); | ||
153 | |||
154 | free(msg); | ||
155 | } | ||
156 | |||
157 | void | ||
158 | test_logf_internal(struct test *t, const char *label, const char *func, | ||
159 | const char *file, int line, const char *fmt, ...) | ||
160 | { | ||
161 | va_list ap; | ||
162 | |||
163 | va_start(ap, fmt); | ||
164 | test_vlogf_internal(t, label, func, file, line, fmt, ap); | ||
165 | va_end(ap); | ||
166 | } | ||
167 | |||
168 | void | ||
169 | test_skip(struct test *t, const char *reason) | ||
170 | { | ||
171 | t->skipped = 1; | ||
172 | test_printf(t, "%s\n", reason); | ||
173 | } | ||
174 | |||
175 | void | ||
176 | test_skipf(struct test *t, const char *fmt, ...) | ||
177 | { | ||
178 | va_list ap; | ||
179 | |||
180 | t->skipped = 1; | ||
181 | |||
182 | va_start(ap, fmt); | ||
183 | test_vprintf(t, fmt, ap); | ||
184 | if (fputc('\n', t->out) == EOF) | ||
185 | err(1, "fputc"); | ||
186 | va_end(ap); | ||
187 | } | ||
188 | |||
189 | void | ||
190 | test_run(struct test *pt, const char *name, test_run_func *fn, const void *arg) | ||
191 | { | ||
192 | struct test *t = test_new(pt, name); | ||
193 | char *status = "PASS"; | ||
194 | char buf[1024]; | ||
195 | size_t buflen; | ||
196 | int ferr; | ||
197 | |||
198 | /* Run test */ | ||
199 | test_printf(t, "=== RUN %s\n", t->name); | ||
200 | fn(t, arg); | ||
201 | |||
202 | if (t->skipped) | ||
203 | status = "SKIP"; | ||
204 | if (t->failed) | ||
205 | status = "FAIL"; | ||
206 | |||
207 | test_printf(t, "--- %s: %s\n\n", status, t->name); | ||
208 | |||
209 | /* Print result of test */ | ||
210 | if (t->failed && t->out != stderr) { | ||
211 | /* Copy logs to stderr */ | ||
212 | rewind(t->out); | ||
213 | while ((buflen = fread(buf, 1, sizeof(buf), t->out)) > 0) | ||
214 | fwrite(buf, 1, buflen, stderr); | ||
215 | if ((ferr = ferror(t->out)) != 0) | ||
216 | errx(1, "ferror: %d", ferr); | ||
217 | } | ||
218 | |||
219 | if (t->out != NULL && t->out != stderr) { | ||
220 | /* Reset output file */ | ||
221 | rewind(t->out); | ||
222 | ftruncate(fileno(t->out), 0); | ||
223 | } | ||
224 | |||
225 | test_cleanup(t); | ||
226 | } | ||