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