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