test_helper.c revision 323136
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
108extern char *__progname;
109
110static int verbose_mode = 0;
111static int quiet_mode = 0;
112static char *active_test_name = NULL;
113static u_int test_number = 0;
114static test_onerror_func_t *test_onerror = NULL;
115static void *onerror_ctx = NULL;
116static const char *data_dir = NULL;
117static char subtest_info[512];
118
119int
120main(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
169const char *
170test_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
186void
187test_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
195static void
196siginfo(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
205void
206test_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
219void
220set_onerror_func(test_onerror_func_t *f, void *ctx)
221{
222	test_onerror = f;
223	onerror_ctx = ctx;
224}
225
226void
227test_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
241void
242test_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
251void
252ssl_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
264static const char *
265pred_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
285static void
286test_die(void)
287{
288	if (test_onerror != NULL)
289		test_onerror(onerror_ctx);
290	abort();
291}
292
293static void
294test_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
305void
306assert_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
318void
319assert_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
336static char *
337tohex(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
353void
354assert_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
373static int
374memvalcmp(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
387void
388assert_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
411void
412assert_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
422void
423assert_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
433void
434assert_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
444void
445assert_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
455void
456assert_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
466void
467assert_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
481void
482assert_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
492void
493assert_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
503void
504assert_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
514void
515assert_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
527void
528assert_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