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