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