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