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