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