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