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