summaryrefslogtreecommitdiff
path: root/src/regress/lib/libcrypto/test/test.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/regress/lib/libcrypto/test/test.c')
-rw-r--r--src/regress/lib/libcrypto/test/test.c225
1 files changed, 225 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..b48711919d
--- /dev/null
+++ b/src/regress/lib/libcrypto/test/test.c
@@ -0,0 +1,225 @@
1/* $OpenBSD: test.c,v 1.1 2025/05/21 08:57:13 joshua 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 <libgen.h>
20#include <stdarg.h>
21#include <stdio.h>
22#include <stdlib.h>
23#include <string.h>
24#include <unistd.h>
25
26#include "test.h"
27
28struct test {
29 struct test *parent;
30 char *name;
31 FILE *out;
32 int skipped;
33 int failed;
34};
35
36static struct test *
37test_new(struct test *pt, const char *name)
38{
39 struct test *t;
40
41 if ((t = calloc(1, sizeof(*t))) == NULL)
42 err(1, "calloc");
43
44 if (name != NULL) {
45 if ((t->name = strdup(name)) == NULL)
46 err(1, "strdup");
47 }
48
49 t->out = pt->out;
50 t->parent = pt;
51
52 return t;
53}
54
55struct test *
56test_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 if ((t->out = fdopen(out_fd, "w+")) == NULL)
77 err(1, "fdopen");
78
79 return t;
80}
81
82static void
83test_cleanup(struct test *t)
84{
85 free(t->name);
86 free(t);
87}
88
89int
90test_result(struct test *t)
91{
92 int failed = t->failed;
93
94 if (t->parent == NULL && t->out != stderr)
95 fclose(t->out);
96
97 test_cleanup(t);
98
99 return failed;
100}
101
102void
103test_fail(struct test *t)
104{
105 t->failed = 1;
106
107 /* Also fail parent. */
108 if (t->parent != NULL)
109 test_fail(t->parent);
110}
111
112static void
113test_vprintf(struct test *t, const char *fmt, va_list ap)
114{
115 if (vfprintf(t->out, fmt, ap) == -1)
116 err(1, "vfprintf");
117}
118
119void
120test_printf(struct test *t, const char *fmt, ...)
121{
122 va_list ap;
123
124 va_start(ap, fmt);
125 test_vprintf(t, fmt, ap);
126 va_end(ap);
127}
128
129static void
130test_vlogf_internal(struct test *t, const char *label, const char *func,
131 const char *file, int line, const char *fmt, va_list ap)
132{
133 char *msg = NULL;
134 char *l = ": ";
135 const char *filename;
136
137 if (label == NULL) {
138 label = "";
139 l = "";
140 }
141
142 if (vasprintf(&msg, fmt, ap) == -1)
143 err(1, "vasprintf");
144
145 if ((filename = strrchr(file, '/')) != NULL)
146 filename++;
147 else
148 filename = file;
149
150 test_printf(t, "%s [%s:%d]%s%s: %s\n",
151 func, filename, line, l, label, msg);
152
153 free(msg);
154}
155
156void
157test_logf_internal(struct test *t, const char *label, const char *func,
158 const char *file, int line, const char *fmt, ...)
159{
160 va_list ap;
161
162 va_start(ap, fmt);
163 test_vlogf_internal(t, label, func, file, line, fmt, ap);
164 va_end(ap);
165}
166
167void
168test_skip(struct test *t, const char *reason)
169{
170 t->skipped = 1;
171 test_printf(t, "%s\n", reason);
172}
173
174void
175test_skipf(struct test *t, const char *fmt, ...)
176{
177 va_list ap;
178
179 t->skipped = 1;
180
181 va_start(ap, fmt);
182 test_vprintf(t, fmt, ap);
183 if (fputc('\n', t->out) == EOF)
184 err(1, "fputc");
185 va_end(ap);
186}
187
188void
189test_run(struct test *pt, const char *name, test_run_func *fn, const void *arg)
190{
191 struct test *t = test_new(pt, name);
192 char *status = "PASS";
193 char buf[1024];
194 size_t buflen;
195 int ferr;
196
197 /* Run test */
198 test_printf(t, "=== RUN %s\n", t->name);
199 fn(t, arg);
200
201 if (t->skipped)
202 status = "SKIP";
203 if (t->failed)
204 status = "FAIL";
205
206 test_printf(t, "--- %s: %s\n\n", status, t->name);
207
208 /* Print result of test */
209 if (t->failed && t->out != stderr) {
210 /* Copy logs to stderr */
211 rewind(t->out);
212 while ((buflen = fread(buf, 1, sizeof(buf), t->out)) > 0)
213 fwrite(buf, 1, buflen, stderr);
214 if ((ferr = ferror(t->out)) != 0)
215 errx(1, "ferror: %d", ferr);
216 }
217
218 if (t->out != NULL && t->out != stderr) {
219 /* Reset output file */
220 rewind(t->out);
221 ftruncate(fileno(t->out), 0);
222 }
223
224 test_cleanup(t);
225}