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