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