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