1 /* $OpenBSD: test_helper.c,v 1.13 2021/12/14 21:25:27 deraadt Exp $ */
2 /*
3 * Copyright (c) 2011 Damien Miller <djm@mindrot.org>
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 /* Utility functions/framework for regress tests */
19
20 #include "includes.h"
21
22 #include <sys/types.h>
23 #include <sys/uio.h>
24
25 #include <stdarg.h>
26 #include <fcntl.h>
27 #include <stdio.h>
28 #ifdef HAVE_STDINT_H
29 # include <stdint.h>
30 #endif
31 #include <stdlib.h>
32 #include <string.h>
33 #include <assert.h>
34 #include <unistd.h>
35 #include <signal.h>
36
37 #ifdef WITH_OPENSSL
38 #include <openssl/bn.h>
39 #include <openssl/err.h>
40 #endif
41
42 #if defined(HAVE_STRNVIS) && defined(HAVE_VIS_H) && !defined(BROKEN_STRNVIS)
43 # include <vis.h>
44 #endif
45
46 #define MINIMUM(a, b) (((a) < (b)) ? (a) : (b))
47
48 #include "entropy.h"
49 #include "test_helper.h"
50 #include "atomicio.h"
51
52 #define TEST_CHECK_INT(r, pred) do { \
53 switch (pred) { \
54 case TEST_EQ: \
55 if (r == 0) \
56 return; \
57 break; \
58 case TEST_NE: \
59 if (r != 0) \
60 return; \
61 break; \
62 case TEST_LT: \
63 if (r < 0) \
64 return; \
65 break; \
66 case TEST_LE: \
67 if (r <= 0) \
68 return; \
69 break; \
70 case TEST_GT: \
71 if (r > 0) \
72 return; \
73 break; \
74 case TEST_GE: \
75 if (r >= 0) \
76 return; \
77 break; \
78 default: \
79 abort(); \
80 } \
81 } while (0)
82
83 #define TEST_CHECK(x1, x2, pred) do { \
84 switch (pred) { \
85 case TEST_EQ: \
86 if (x1 == x2) \
87 return; \
88 break; \
89 case TEST_NE: \
90 if (x1 != x2) \
91 return; \
92 break; \
93 case TEST_LT: \
94 if (x1 < x2) \
95 return; \
96 break; \
97 case TEST_LE: \
98 if (x1 <= x2) \
99 return; \
100 break; \
101 case TEST_GT: \
102 if (x1 > x2) \
103 return; \
104 break; \
105 case TEST_GE: \
106 if (x1 >= x2) \
107 return; \
108 break; \
109 default: \
110 abort(); \
111 } \
112 } while (0)
113
114 extern char *__progname;
115
116 static int verbose_mode = 0;
117 static int quiet_mode = 0;
118 static char *active_test_name = NULL;
119 static u_int test_number = 0;
120 static test_onerror_func_t *test_onerror = NULL;
121 static void *onerror_ctx = NULL;
122 static const char *data_dir = NULL;
123 static char subtest_info[512];
124 static int fast = 0;
125 static int slow = 0;
126
127 int
main(int argc,char ** argv)128 main(int argc, char **argv)
129 {
130 int ch;
131
132 seed_rng();
133 #ifdef WITH_OPENSSL
134 ERR_load_crypto_strings();
135 #endif
136
137 /* Handle systems without __progname */
138 if (__progname == NULL) {
139 __progname = strrchr(argv[0], '/');
140 if (__progname == NULL || __progname[1] == '\0')
141 __progname = argv[0];
142 else
143 __progname++;
144 if ((__progname = strdup(__progname)) == NULL) {
145 fprintf(stderr, "strdup failed\n");
146 exit(1);
147 }
148 }
149
150 while ((ch = getopt(argc, argv, "Ffvqd:")) != -1) {
151 switch (ch) {
152 case 'F':
153 slow = 1;
154 break;
155 case 'f':
156 fast = 1;
157 break;
158 case 'd':
159 data_dir = optarg;
160 break;
161 case 'q':
162 verbose_mode = 0;
163 quiet_mode = 1;
164 break;
165 case 'v':
166 verbose_mode = 1;
167 quiet_mode = 0;
168 break;
169 default:
170 fprintf(stderr, "Unrecognised command line option\n");
171 fprintf(stderr, "Usage: %s [-v]\n", __progname);
172 exit(1);
173 }
174 }
175 setvbuf(stdout, NULL, _IONBF, 0);
176 if (!quiet_mode)
177 printf("%s: ", __progname);
178 if (verbose_mode)
179 printf("\n");
180
181 tests();
182
183 if (!quiet_mode)
184 printf(" %u tests ok\n", test_number);
185 return 0;
186 }
187
188 int
test_is_verbose(void)189 test_is_verbose(void)
190 {
191 return verbose_mode;
192 }
193
194 int
test_is_quiet(void)195 test_is_quiet(void)
196 {
197 return quiet_mode;
198 }
199
200 int
test_is_fast(void)201 test_is_fast(void)
202 {
203 return fast;
204 }
205
206 int
test_is_slow(void)207 test_is_slow(void)
208 {
209 return slow;
210 }
211
212 const char *
test_data_file(const char * name)213 test_data_file(const char *name)
214 {
215 static char ret[PATH_MAX];
216
217 if (data_dir != NULL)
218 snprintf(ret, sizeof(ret), "%s/%s", data_dir, name);
219 else
220 strlcpy(ret, name, sizeof(ret));
221 if (access(ret, F_OK) != 0) {
222 fprintf(stderr, "Cannot access data file %s: %s\n",
223 ret, strerror(errno));
224 exit(1);
225 }
226 return ret;
227 }
228
229 void
test_info(char * s,size_t len)230 test_info(char *s, size_t len)
231 {
232 snprintf(s, len, "In test %u: \"%s\"%s%s\n", test_number,
233 active_test_name == NULL ? "<none>" : active_test_name,
234 *subtest_info != '\0' ? " - " : "", subtest_info);
235 }
236
237 static void
siginfo(int unused)238 siginfo(int unused __attribute__((__unused__)))
239 {
240 char buf[256];
241
242 test_info(buf, sizeof(buf));
243 atomicio(vwrite, STDERR_FILENO, buf, strlen(buf));
244 }
245
246 void
test_start(const char * n)247 test_start(const char *n)
248 {
249 assert(active_test_name == NULL);
250 assert((active_test_name = strdup(n)) != NULL);
251 *subtest_info = '\0';
252 if (verbose_mode)
253 printf("test %u - \"%s\": ", test_number, active_test_name);
254 test_number++;
255 #ifdef SIGINFO
256 signal(SIGINFO, siginfo);
257 #endif
258 signal(SIGUSR1, siginfo);
259 }
260
261 void
set_onerror_func(test_onerror_func_t * f,void * ctx)262 set_onerror_func(test_onerror_func_t *f, void *ctx)
263 {
264 test_onerror = f;
265 onerror_ctx = ctx;
266 }
267
268 void
test_done(void)269 test_done(void)
270 {
271 *subtest_info = '\0';
272 assert(active_test_name != NULL);
273 free(active_test_name);
274 active_test_name = NULL;
275 if (verbose_mode)
276 printf("OK\n");
277 else if (!quiet_mode) {
278 printf(".");
279 fflush(stdout);
280 }
281 }
282
283 void
test_subtest_info(const char * fmt,...)284 test_subtest_info(const char *fmt, ...)
285 {
286 va_list ap;
287
288 va_start(ap, fmt);
289 vsnprintf(subtest_info, sizeof(subtest_info), fmt, ap);
290 va_end(ap);
291 }
292
293 void
ssl_err_check(const char * file,int line)294 ssl_err_check(const char *file, int line)
295 {
296 #ifdef WITH_OPENSSL
297 long openssl_error = ERR_get_error();
298
299 if (openssl_error == 0)
300 return;
301
302 fprintf(stderr, "\n%s:%d: uncaught OpenSSL error: %s",
303 file, line, ERR_error_string(openssl_error, NULL));
304 #else /* WITH_OPENSSL */
305 fprintf(stderr, "\n%s:%d: uncaught OpenSSL error ",
306 file, line);
307 #endif /* WITH_OPENSSL */
308 abort();
309 }
310
311 static const char *
pred_name(enum test_predicate p)312 pred_name(enum test_predicate p)
313 {
314 switch (p) {
315 case TEST_EQ:
316 return "EQ";
317 case TEST_NE:
318 return "NE";
319 case TEST_LT:
320 return "LT";
321 case TEST_LE:
322 return "LE";
323 case TEST_GT:
324 return "GT";
325 case TEST_GE:
326 return "GE";
327 default:
328 return "UNKNOWN";
329 }
330 }
331
332 static void
test_die(void)333 test_die(void)
334 {
335 if (test_onerror != NULL)
336 test_onerror(onerror_ctx);
337 abort();
338 }
339
340 static void
test_header(const char * file,int line,const char * a1,const char * a2,const char * name,enum test_predicate pred)341 test_header(const char *file, int line, const char *a1, const char *a2,
342 const char *name, enum test_predicate pred)
343 {
344 fprintf(stderr, "\n%s:%d test #%u \"%s\"%s%s\n",
345 file, line, test_number, active_test_name,
346 *subtest_info != '\0' ? " - " : "", subtest_info);
347 fprintf(stderr, "ASSERT_%s_%s(%s%s%s) failed:\n",
348 name, pred_name(pred), a1,
349 a2 != NULL ? ", " : "", a2 != NULL ? a2 : "");
350 }
351
352 #ifdef WITH_OPENSSL
353 void
assert_bignum(const char * file,int line,const char * a1,const char * a2,const BIGNUM * aa1,const BIGNUM * aa2,enum test_predicate pred)354 assert_bignum(const char *file, int line, const char *a1, const char *a2,
355 const BIGNUM *aa1, const BIGNUM *aa2, enum test_predicate pred)
356 {
357 int r = BN_cmp(aa1, aa2);
358
359 TEST_CHECK_INT(r, pred);
360 test_header(file, line, a1, a2, "BIGNUM", pred);
361 fprintf(stderr, "%12s = 0x%s\n", a1, BN_bn2hex(aa1));
362 fprintf(stderr, "%12s = 0x%s\n", a2, BN_bn2hex(aa2));
363 test_die();
364 }
365 #endif
366
367 void
assert_string(const char * file,int line,const char * a1,const char * a2,const char * aa1,const char * aa2,enum test_predicate pred)368 assert_string(const char *file, int line, const char *a1, const char *a2,
369 const char *aa1, const char *aa2, enum test_predicate pred)
370 {
371 int r;
372
373 /* Verify pointers are not NULL */
374 assert_ptr(file, line, a1, "NULL", aa1, NULL, TEST_NE);
375 assert_ptr(file, line, a2, "NULL", aa2, NULL, TEST_NE);
376
377 r = strcmp(aa1, aa2);
378 TEST_CHECK_INT(r, pred);
379 test_header(file, line, a1, a2, "STRING", pred);
380 fprintf(stderr, "%12s = %s (len %zu)\n", a1, aa1, strlen(aa1));
381 fprintf(stderr, "%12s = %s (len %zu)\n", a2, aa2, strlen(aa2));
382 test_die();
383 }
384
385 static char *
tohex(const void * _s,size_t l)386 tohex(const void *_s, size_t l)
387 {
388 u_int8_t *s = (u_int8_t *)_s;
389 size_t i, j;
390 const char *hex = "0123456789abcdef";
391 char *r = malloc((l * 2) + 1);
392
393 assert(r != NULL);
394 for (i = j = 0; i < l; i++) {
395 r[j++] = hex[(s[i] >> 4) & 0xf];
396 r[j++] = hex[s[i] & 0xf];
397 }
398 r[j] = '\0';
399 return r;
400 }
401
402 void
assert_mem(const char * file,int line,const char * a1,const char * a2,const void * aa1,const void * aa2,size_t l,enum test_predicate pred)403 assert_mem(const char *file, int line, const char *a1, const char *a2,
404 const void *aa1, const void *aa2, size_t l, enum test_predicate pred)
405 {
406 int r;
407 char *aa1_tohex = NULL;
408 char *aa2_tohex = NULL;
409
410 if (l == 0)
411 return;
412 /* If length is >0, then verify pointers are not NULL */
413 assert_ptr(file, line, a1, "NULL", aa1, NULL, TEST_NE);
414 assert_ptr(file, line, a2, "NULL", aa2, NULL, TEST_NE);
415
416 r = memcmp(aa1, aa2, l);
417 TEST_CHECK_INT(r, pred);
418 test_header(file, line, a1, a2, "STRING", pred);
419 aa1_tohex = tohex(aa1, MINIMUM(l, 256));
420 aa2_tohex = tohex(aa2, MINIMUM(l, 256));
421 fprintf(stderr, "%12s = %s (len %zu)\n", a1, aa1_tohex, l);
422 fprintf(stderr, "%12s = %s (len %zu)\n", a2, aa2_tohex, l);
423 free(aa1_tohex);
424 free(aa2_tohex);
425 test_die();
426 }
427
428 static int
memvalcmp(const u_int8_t * s,u_char v,size_t l,size_t * where)429 memvalcmp(const u_int8_t *s, u_char v, size_t l, size_t *where)
430 {
431 size_t i;
432
433 for (i = 0; i < l; i++) {
434 if (s[i] != v) {
435 *where = i;
436 return 1;
437 }
438 }
439 return 0;
440 }
441
442 void
assert_mem_filled(const char * file,int line,const char * a1,const void * aa1,u_char v,size_t l,enum test_predicate pred)443 assert_mem_filled(const char *file, int line, const char *a1,
444 const void *aa1, u_char v, size_t l, enum test_predicate pred)
445 {
446 size_t where = -1;
447 int r;
448 char tmp[64];
449 char *aa1_tohex = NULL;
450
451 if (l == 0)
452 return;
453 /* If length is >0, then verify the pointer is not NULL */
454 assert_ptr(file, line, a1, "NULL", aa1, NULL, TEST_NE);
455
456 r = memvalcmp(aa1, v, l, &where);
457 TEST_CHECK_INT(r, pred);
458 test_header(file, line, a1, NULL, "MEM_ZERO", pred);
459 aa1_tohex = tohex(aa1, MINIMUM(l, 20));
460 fprintf(stderr, "%20s = %s%s (len %zu)\n", a1,
461 aa1_tohex, l > 20 ? "..." : "", l);
462 free(aa1_tohex);
463 snprintf(tmp, sizeof(tmp), "(%s)[%zu]", a1, where);
464 fprintf(stderr, "%20s = 0x%02x (expected 0x%02x)\n", tmp,
465 ((u_char *)aa1)[where], v);
466 test_die();
467 }
468
469 void
assert_int(const char * file,int line,const char * a1,const char * a2,int aa1,int aa2,enum test_predicate pred)470 assert_int(const char *file, int line, const char *a1, const char *a2,
471 int aa1, int aa2, enum test_predicate pred)
472 {
473 TEST_CHECK(aa1, aa2, pred);
474 test_header(file, line, a1, a2, "INT", pred);
475 fprintf(stderr, "%12s = %d\n", a1, aa1);
476 fprintf(stderr, "%12s = %d\n", a2, aa2);
477 test_die();
478 }
479
480 void
assert_size_t(const char * file,int line,const char * a1,const char * a2,size_t aa1,size_t aa2,enum test_predicate pred)481 assert_size_t(const char *file, int line, const char *a1, const char *a2,
482 size_t aa1, size_t aa2, enum test_predicate pred)
483 {
484 TEST_CHECK(aa1, aa2, pred);
485 test_header(file, line, a1, a2, "SIZE_T", pred);
486 fprintf(stderr, "%12s = %zu\n", a1, aa1);
487 fprintf(stderr, "%12s = %zu\n", a2, aa2);
488 test_die();
489 }
490
491 void
assert_u_int(const char * file,int line,const char * a1,const char * a2,u_int aa1,u_int aa2,enum test_predicate pred)492 assert_u_int(const char *file, int line, const char *a1, const char *a2,
493 u_int aa1, u_int aa2, enum test_predicate pred)
494 {
495 TEST_CHECK(aa1, aa2, pred);
496 test_header(file, line, a1, a2, "U_INT", pred);
497 fprintf(stderr, "%12s = %u / 0x%x\n", a1, aa1, aa1);
498 fprintf(stderr, "%12s = %u / 0x%x\n", a2, aa2, aa2);
499 test_die();
500 }
501
502 void
assert_long(const char * file,int line,const char * a1,const char * a2,long aa1,long aa2,enum test_predicate pred)503 assert_long(const char *file, int line, const char *a1, const char *a2,
504 long aa1, long aa2, enum test_predicate pred)
505 {
506 TEST_CHECK(aa1, aa2, pred);
507 test_header(file, line, a1, a2, "LONG", pred);
508 fprintf(stderr, "%12s = %ld / 0x%lx\n", a1, aa1, aa1);
509 fprintf(stderr, "%12s = %ld / 0x%lx\n", a2, aa2, aa2);
510 test_die();
511 }
512
513 void
assert_long_long(const char * file,int line,const char * a1,const char * a2,long long aa1,long long aa2,enum test_predicate pred)514 assert_long_long(const char *file, int line, const char *a1, const char *a2,
515 long long aa1, long long aa2, enum test_predicate pred)
516 {
517 TEST_CHECK(aa1, aa2, pred);
518 test_header(file, line, a1, a2, "LONG LONG", pred);
519 fprintf(stderr, "%12s = %lld / 0x%llx\n", a1, aa1, aa1);
520 fprintf(stderr, "%12s = %lld / 0x%llx\n", a2, aa2, aa2);
521 test_die();
522 }
523
524 void
assert_char(const char * file,int line,const char * a1,const char * a2,char aa1,char aa2,enum test_predicate pred)525 assert_char(const char *file, int line, const char *a1, const char *a2,
526 char aa1, char aa2, enum test_predicate pred)
527 {
528 char buf[8];
529
530 TEST_CHECK(aa1, aa2, pred);
531 test_header(file, line, a1, a2, "CHAR", pred);
532 fprintf(stderr, "%12s = '%s' / 0x02%x\n", a1,
533 vis(buf, aa1, VIS_SAFE|VIS_NL|VIS_TAB|VIS_OCTAL, 0), aa1);
534 fprintf(stderr, "%12s = '%s' / 0x02%x\n", a1,
535 vis(buf, aa2, VIS_SAFE|VIS_NL|VIS_TAB|VIS_OCTAL, 0), aa2);
536 test_die();
537 }
538
539 void
assert_u8(const char * file,int line,const char * a1,const char * a2,u_int8_t aa1,u_int8_t aa2,enum test_predicate pred)540 assert_u8(const char *file, int line, const char *a1, const char *a2,
541 u_int8_t aa1, u_int8_t aa2, enum test_predicate pred)
542 {
543 TEST_CHECK(aa1, aa2, pred);
544 test_header(file, line, a1, a2, "U8", pred);
545 fprintf(stderr, "%12s = 0x%02x %u\n", a1, aa1, aa1);
546 fprintf(stderr, "%12s = 0x%02x %u\n", a2, aa2, aa2);
547 test_die();
548 }
549
550 void
assert_u16(const char * file,int line,const char * a1,const char * a2,u_int16_t aa1,u_int16_t aa2,enum test_predicate pred)551 assert_u16(const char *file, int line, const char *a1, const char *a2,
552 u_int16_t aa1, u_int16_t aa2, enum test_predicate pred)
553 {
554 TEST_CHECK(aa1, aa2, pred);
555 test_header(file, line, a1, a2, "U16", pred);
556 fprintf(stderr, "%12s = 0x%04x %u\n", a1, aa1, aa1);
557 fprintf(stderr, "%12s = 0x%04x %u\n", a2, aa2, aa2);
558 test_die();
559 }
560
561 void
assert_u32(const char * file,int line,const char * a1,const char * a2,u_int32_t aa1,u_int32_t aa2,enum test_predicate pred)562 assert_u32(const char *file, int line, const char *a1, const char *a2,
563 u_int32_t aa1, u_int32_t aa2, enum test_predicate pred)
564 {
565 TEST_CHECK(aa1, aa2, pred);
566 test_header(file, line, a1, a2, "U32", pred);
567 fprintf(stderr, "%12s = 0x%08x %u\n", a1, aa1, aa1);
568 fprintf(stderr, "%12s = 0x%08x %u\n", a2, aa2, aa2);
569 test_die();
570 }
571
572 void
assert_u64(const char * file,int line,const char * a1,const char * a2,u_int64_t aa1,u_int64_t aa2,enum test_predicate pred)573 assert_u64(const char *file, int line, const char *a1, const char *a2,
574 u_int64_t aa1, u_int64_t aa2, enum test_predicate pred)
575 {
576 TEST_CHECK(aa1, aa2, pred);
577 test_header(file, line, a1, a2, "U64", pred);
578 fprintf(stderr, "%12s = 0x%016llx %llu\n", a1,
579 (unsigned long long)aa1, (unsigned long long)aa1);
580 fprintf(stderr, "%12s = 0x%016llx %llu\n", a2,
581 (unsigned long long)aa2, (unsigned long long)aa2);
582 test_die();
583 }
584
585 void
assert_ptr(const char * file,int line,const char * a1,const char * a2,const void * aa1,const void * aa2,enum test_predicate pred)586 assert_ptr(const char *file, int line, const char *a1, const char *a2,
587 const void *aa1, const void *aa2, enum test_predicate pred)
588 {
589 TEST_CHECK(aa1, aa2, pred);
590 test_header(file, line, a1, a2, "PTR", pred);
591 fprintf(stderr, "%12s = %p\n", a1, aa1);
592 fprintf(stderr, "%12s = %p\n", a2, aa2);
593 test_die();
594 }
595
596