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