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