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