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