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