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