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