diff options
Diffstat (limited to '')
-rw-r--r-- | regress/unittests/test_helper/Makefile | 15 | ||||
-rw-r--r-- | regress/unittests/test_helper/fuzz.c | 438 | ||||
-rw-r--r-- | regress/unittests/test_helper/test_helper.c | 594 | ||||
-rw-r--r-- | regress/unittests/test_helper/test_helper.h | 326 |
4 files changed, 1373 insertions, 0 deletions
diff --git a/regress/unittests/test_helper/Makefile b/regress/unittests/test_helper/Makefile new file mode 100644 index 0000000..78026e6 --- /dev/null +++ b/regress/unittests/test_helper/Makefile @@ -0,0 +1,15 @@ +# $OpenBSD: Makefile,v 1.3 2016/07/04 18:01:44 guenther Exp $ + +LIB= test_helper +SRCS= test_helper.c fuzz.c + +NOPROFILE= yes +NOPIC= yes + +# Hack to allow building with SUBDIR in ../../Makefile +regress: all + +install: + @echo -n + +.include <bsd.lib.mk> diff --git a/regress/unittests/test_helper/fuzz.c b/regress/unittests/test_helper/fuzz.c new file mode 100644 index 0000000..78b3665 --- /dev/null +++ b/regress/unittests/test_helper/fuzz.c @@ -0,0 +1,438 @@ +/* $OpenBSD: fuzz.c,v 1.8 2015/03/03 20:42:49 djm Exp $ */ +/* + * Copyright (c) 2011 Damien Miller <djm@mindrot.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* Utility functions/framework for fuzz tests */ + +#include "includes.h" + +#include <sys/types.h> +#include <sys/uio.h> + +#include <assert.h> +#include <ctype.h> +#include <stdio.h> +#ifdef HAVE_STDINT_H +# include <stdint.h> +#endif +#include <stdlib.h> +#include <string.h> +#include <signal.h> +#include <unistd.h> + +#include "test_helper.h" +#include "atomicio.h" + +/* #define FUZZ_DEBUG */ + +#ifdef FUZZ_DEBUG +# define FUZZ_DBG(x) do { \ + printf("%s:%d %s: ", __FILE__, __LINE__, __func__); \ + printf x; \ + printf("\n"); \ + fflush(stdout); \ + } while (0) +#else +# define FUZZ_DBG(x) +#endif + +/* For brevity later */ +typedef unsigned long long fuzz_ullong; + +/* For base-64 fuzzing */ +static const char fuzz_b64chars[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +struct fuzz { + /* Fuzz method currently in use */ + int strategy; + + /* Fuzz methods remaining */ + int strategies; + + /* Original seed data blob */ + void *seed; + size_t slen; + + /* Current working copy of seed with fuzz mutations applied */ + u_char *fuzzed; + + /* Used by fuzz methods */ + size_t o1, o2; +}; + +static const char * +fuzz_ntop(u_int n) +{ + switch (n) { + case 0: + return "NONE"; + case FUZZ_1_BIT_FLIP: + return "FUZZ_1_BIT_FLIP"; + case FUZZ_2_BIT_FLIP: + return "FUZZ_2_BIT_FLIP"; + case FUZZ_1_BYTE_FLIP: + return "FUZZ_1_BYTE_FLIP"; + case FUZZ_2_BYTE_FLIP: + return "FUZZ_2_BYTE_FLIP"; + case FUZZ_TRUNCATE_START: + return "FUZZ_TRUNCATE_START"; + case FUZZ_TRUNCATE_END: + return "FUZZ_TRUNCATE_END"; + case FUZZ_BASE64: + return "FUZZ_BASE64"; + default: + abort(); + } +} + +static int +fuzz_fmt(struct fuzz *fuzz, char *s, size_t n) +{ + if (fuzz == NULL) + return -1; + + switch (fuzz->strategy) { + case FUZZ_1_BIT_FLIP: + snprintf(s, n, "%s case %zu of %zu (bit: %zu)\n", + fuzz_ntop(fuzz->strategy), + fuzz->o1, fuzz->slen * 8, fuzz->o1); + return 0; + case FUZZ_2_BIT_FLIP: + snprintf(s, n, "%s case %llu of %llu (bits: %zu, %zu)\n", + fuzz_ntop(fuzz->strategy), + (((fuzz_ullong)fuzz->o2) * fuzz->slen * 8) + fuzz->o1, + ((fuzz_ullong)fuzz->slen * 8) * fuzz->slen * 8, + fuzz->o1, fuzz->o2); + return 0; + case FUZZ_1_BYTE_FLIP: + snprintf(s, n, "%s case %zu of %zu (byte: %zu)\n", + fuzz_ntop(fuzz->strategy), + fuzz->o1, fuzz->slen, fuzz->o1); + return 0; + case FUZZ_2_BYTE_FLIP: + snprintf(s, n, "%s case %llu of %llu (bytes: %zu, %zu)\n", + fuzz_ntop(fuzz->strategy), + (((fuzz_ullong)fuzz->o2) * fuzz->slen) + fuzz->o1, + ((fuzz_ullong)fuzz->slen) * fuzz->slen, + fuzz->o1, fuzz->o2); + return 0; + case FUZZ_TRUNCATE_START: + snprintf(s, n, "%s case %zu of %zu (offset: %zu)\n", + fuzz_ntop(fuzz->strategy), + fuzz->o1, fuzz->slen, fuzz->o1); + return 0; + case FUZZ_TRUNCATE_END: + snprintf(s, n, "%s case %zu of %zu (offset: %zu)\n", + fuzz_ntop(fuzz->strategy), + fuzz->o1, fuzz->slen, fuzz->o1); + return 0; + case FUZZ_BASE64: + assert(fuzz->o2 < sizeof(fuzz_b64chars) - 1); + snprintf(s, n, "%s case %llu of %llu (offset: %zu char: %c)\n", + fuzz_ntop(fuzz->strategy), + (fuzz->o1 * (fuzz_ullong)64) + fuzz->o2, + fuzz->slen * (fuzz_ullong)64, fuzz->o1, + fuzz_b64chars[fuzz->o2]); + return 0; + default: + return -1; + abort(); + } +} + +static void +dump(u_char *p, size_t len) +{ + size_t i, j; + + for (i = 0; i < len; i += 16) { + fprintf(stderr, "%.4zd: ", i); + for (j = i; j < i + 16; j++) { + if (j < len) + fprintf(stderr, "%02x ", p[j]); + else + fprintf(stderr, " "); + } + fprintf(stderr, " "); + for (j = i; j < i + 16; j++) { + if (j < len) { + if (isascii(p[j]) && isprint(p[j])) + fprintf(stderr, "%c", p[j]); + else + fprintf(stderr, "."); + } + } + fprintf(stderr, "\n"); + } +} + +void +fuzz_dump(struct fuzz *fuzz) +{ + char buf[256]; + + if (fuzz_fmt(fuzz, buf, sizeof(buf)) != 0) { + fprintf(stderr, "%s: fuzz invalid\n", __func__); + abort(); + } + fputs(buf, stderr); + fprintf(stderr, "fuzz original %p len = %zu\n", fuzz->seed, fuzz->slen); + dump(fuzz->seed, fuzz->slen); + fprintf(stderr, "fuzz context %p len = %zu\n", fuzz, fuzz_len(fuzz)); + dump(fuzz_ptr(fuzz), fuzz_len(fuzz)); +} + +static struct fuzz *last_fuzz; + +static void +siginfo(int unused __attribute__((__unused__))) +{ + char buf[256]; + + test_info(buf, sizeof(buf)); + atomicio(vwrite, STDERR_FILENO, buf, strlen(buf)); + if (last_fuzz != NULL) { + fuzz_fmt(last_fuzz, buf, sizeof(buf)); + atomicio(vwrite, STDERR_FILENO, buf, strlen(buf)); + } +} + +struct fuzz * +fuzz_begin(u_int strategies, const void *p, size_t l) +{ + struct fuzz *ret = calloc(sizeof(*ret), 1); + + assert(p != NULL); + assert(ret != NULL); + ret->seed = malloc(l); + assert(ret->seed != NULL); + memcpy(ret->seed, p, l); + ret->slen = l; + ret->strategies = strategies; + + assert(ret->slen < SIZE_MAX / 8); + assert(ret->strategies <= (FUZZ_MAX|(FUZZ_MAX-1))); + + FUZZ_DBG(("begin, ret = %p", ret)); + + fuzz_next(ret); + + last_fuzz = ret; +#ifdef SIGINFO + signal(SIGINFO, siginfo); +#endif + signal(SIGUSR1, siginfo); + + return ret; +} + +void +fuzz_cleanup(struct fuzz *fuzz) +{ + FUZZ_DBG(("cleanup, fuzz = %p", fuzz)); + last_fuzz = NULL; +#ifdef SIGINFO + signal(SIGINFO, SIG_DFL); +#endif + signal(SIGUSR1, SIG_DFL); + assert(fuzz != NULL); + assert(fuzz->seed != NULL); + assert(fuzz->fuzzed != NULL); + free(fuzz->seed); + free(fuzz->fuzzed); + free(fuzz); +} + +static int +fuzz_strategy_done(struct fuzz *fuzz) +{ + FUZZ_DBG(("fuzz = %p, strategy = %s, o1 = %zu, o2 = %zu, slen = %zu", + fuzz, fuzz_ntop(fuzz->strategy), fuzz->o1, fuzz->o2, fuzz->slen)); + + switch (fuzz->strategy) { + case FUZZ_1_BIT_FLIP: + return fuzz->o1 >= fuzz->slen * 8; + case FUZZ_2_BIT_FLIP: + return fuzz->o2 >= fuzz->slen * 8; + case FUZZ_2_BYTE_FLIP: + return fuzz->o2 >= fuzz->slen; + case FUZZ_1_BYTE_FLIP: + case FUZZ_TRUNCATE_START: + case FUZZ_TRUNCATE_END: + case FUZZ_BASE64: + return fuzz->o1 >= fuzz->slen; + default: + abort(); + } +} + +void +fuzz_next(struct fuzz *fuzz) +{ + u_int i; + + FUZZ_DBG(("start, fuzz = %p, strategy = %s, strategies = 0x%lx, " + "o1 = %zu, o2 = %zu, slen = %zu", fuzz, fuzz_ntop(fuzz->strategy), + (u_long)fuzz->strategies, fuzz->o1, fuzz->o2, fuzz->slen)); + + if (fuzz->strategy == 0 || fuzz_strategy_done(fuzz)) { + /* If we are just starting out, we need to allocate too */ + if (fuzz->fuzzed == NULL) { + FUZZ_DBG(("alloc")); + fuzz->fuzzed = calloc(fuzz->slen, 1); + } + /* Pick next strategy */ + FUZZ_DBG(("advance")); + for (i = 1; i <= FUZZ_MAX; i <<= 1) { + if ((fuzz->strategies & i) != 0) { + fuzz->strategy = i; + break; + } + } + FUZZ_DBG(("selected = %u", fuzz->strategy)); + if (fuzz->strategy == 0) { + FUZZ_DBG(("done, no more strategies")); + return; + } + fuzz->strategies &= ~(fuzz->strategy); + fuzz->o1 = fuzz->o2 = 0; + } + + assert(fuzz->fuzzed != NULL); + + switch (fuzz->strategy) { + case FUZZ_1_BIT_FLIP: + assert(fuzz->o1 / 8 < fuzz->slen); + memcpy(fuzz->fuzzed, fuzz->seed, fuzz->slen); + fuzz->fuzzed[fuzz->o1 / 8] ^= 1 << (fuzz->o1 % 8); + fuzz->o1++; + break; + case FUZZ_2_BIT_FLIP: + assert(fuzz->o1 / 8 < fuzz->slen); + assert(fuzz->o2 / 8 < fuzz->slen); + memcpy(fuzz->fuzzed, fuzz->seed, fuzz->slen); + fuzz->fuzzed[fuzz->o1 / 8] ^= 1 << (fuzz->o1 % 8); + fuzz->fuzzed[fuzz->o2 / 8] ^= 1 << (fuzz->o2 % 8); + fuzz->o1++; + if (fuzz->o1 >= fuzz->slen * 8) { + fuzz->o1 = 0; + fuzz->o2++; + } + break; + case FUZZ_1_BYTE_FLIP: + assert(fuzz->o1 < fuzz->slen); + memcpy(fuzz->fuzzed, fuzz->seed, fuzz->slen); + fuzz->fuzzed[fuzz->o1] ^= 0xff; + fuzz->o1++; + break; + case FUZZ_2_BYTE_FLIP: + assert(fuzz->o1 < fuzz->slen); + assert(fuzz->o2 < fuzz->slen); + memcpy(fuzz->fuzzed, fuzz->seed, fuzz->slen); + fuzz->fuzzed[fuzz->o1] ^= 0xff; + fuzz->fuzzed[fuzz->o2] ^= 0xff; + fuzz->o1++; + if (fuzz->o1 >= fuzz->slen) { + fuzz->o1 = 0; + fuzz->o2++; + } + break; + case FUZZ_TRUNCATE_START: + case FUZZ_TRUNCATE_END: + assert(fuzz->o1 < fuzz->slen); + memcpy(fuzz->fuzzed, fuzz->seed, fuzz->slen); + fuzz->o1++; + break; + case FUZZ_BASE64: + assert(fuzz->o1 < fuzz->slen); + assert(fuzz->o2 < sizeof(fuzz_b64chars) - 1); + memcpy(fuzz->fuzzed, fuzz->seed, fuzz->slen); + fuzz->fuzzed[fuzz->o1] = fuzz_b64chars[fuzz->o2]; + fuzz->o2++; + if (fuzz->o2 >= sizeof(fuzz_b64chars) - 1) { + fuzz->o2 = 0; + fuzz->o1++; + } + break; + default: + abort(); + } + + FUZZ_DBG(("done, fuzz = %p, strategy = %s, strategies = 0x%lx, " + "o1 = %zu, o2 = %zu, slen = %zu", fuzz, fuzz_ntop(fuzz->strategy), + (u_long)fuzz->strategies, fuzz->o1, fuzz->o2, fuzz->slen)); +} + +int +fuzz_matches_original(struct fuzz *fuzz) +{ + if (fuzz_len(fuzz) != fuzz->slen) + return 0; + return memcmp(fuzz_ptr(fuzz), fuzz->seed, fuzz->slen) == 0; +} + +int +fuzz_done(struct fuzz *fuzz) +{ + FUZZ_DBG(("fuzz = %p, strategies = 0x%lx", fuzz, + (u_long)fuzz->strategies)); + + return fuzz_strategy_done(fuzz) && fuzz->strategies == 0; +} + +size_t +fuzz_len(struct fuzz *fuzz) +{ + assert(fuzz->fuzzed != NULL); + switch (fuzz->strategy) { + case FUZZ_1_BIT_FLIP: + case FUZZ_2_BIT_FLIP: + case FUZZ_1_BYTE_FLIP: + case FUZZ_2_BYTE_FLIP: + case FUZZ_BASE64: + return fuzz->slen; + case FUZZ_TRUNCATE_START: + case FUZZ_TRUNCATE_END: + assert(fuzz->o1 <= fuzz->slen); + return fuzz->slen - fuzz->o1; + default: + abort(); + } +} + +u_char * +fuzz_ptr(struct fuzz *fuzz) +{ + assert(fuzz->fuzzed != NULL); + switch (fuzz->strategy) { + case FUZZ_1_BIT_FLIP: + case FUZZ_2_BIT_FLIP: + case FUZZ_1_BYTE_FLIP: + case FUZZ_2_BYTE_FLIP: + case FUZZ_BASE64: + return fuzz->fuzzed; + case FUZZ_TRUNCATE_START: + assert(fuzz->o1 <= fuzz->slen); + return fuzz->fuzzed + fuzz->o1; + case FUZZ_TRUNCATE_END: + assert(fuzz->o1 <= fuzz->slen); + return fuzz->fuzzed; + default: + abort(); + } +} + diff --git a/regress/unittests/test_helper/test_helper.c b/regress/unittests/test_helper/test_helper.c new file mode 100644 index 0000000..9014ce8 --- /dev/null +++ b/regress/unittests/test_helper/test_helper.c @@ -0,0 +1,594 @@ +/* $OpenBSD: test_helper.c,v 1.12 2019/08/02 01:41:24 djm Exp $ */ +/* + * Copyright (c) 2011 Damien Miller <djm@mindrot.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* Utility functions/framework for regress tests */ + +#include "includes.h" + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/uio.h> + +#include <stdarg.h> +#include <fcntl.h> +#include <stdio.h> +#ifdef HAVE_STDINT_H +# include <stdint.h> +#endif +#include <stdlib.h> +#include <string.h> +#include <assert.h> +#include <unistd.h> +#include <signal.h> + +#ifdef WITH_OPENSSL +#include <openssl/bn.h> +#include <openssl/err.h> +#endif + +#if defined(HAVE_STRNVIS) && defined(HAVE_VIS_H) && !defined(BROKEN_STRNVIS) +# include <vis.h> +#endif + +#include "entropy.h" +#include "test_helper.h" +#include "atomicio.h" + +#define TEST_CHECK_INT(r, pred) do { \ + switch (pred) { \ + case TEST_EQ: \ + if (r == 0) \ + return; \ + break; \ + case TEST_NE: \ + if (r != 0) \ + return; \ + break; \ + case TEST_LT: \ + if (r < 0) \ + return; \ + break; \ + case TEST_LE: \ + if (r <= 0) \ + return; \ + break; \ + case TEST_GT: \ + if (r > 0) \ + return; \ + break; \ + case TEST_GE: \ + if (r >= 0) \ + return; \ + break; \ + default: \ + abort(); \ + } \ + } while (0) + +#define TEST_CHECK(x1, x2, pred) do { \ + switch (pred) { \ + case TEST_EQ: \ + if (x1 == x2) \ + return; \ + break; \ + case TEST_NE: \ + if (x1 != x2) \ + return; \ + break; \ + case TEST_LT: \ + if (x1 < x2) \ + return; \ + break; \ + case TEST_LE: \ + if (x1 <= x2) \ + return; \ + break; \ + case TEST_GT: \ + if (x1 > x2) \ + return; \ + break; \ + case TEST_GE: \ + if (x1 >= x2) \ + return; \ + break; \ + default: \ + abort(); \ + } \ + } while (0) + +extern char *__progname; + +static int verbose_mode = 0; +static int quiet_mode = 0; +static char *active_test_name = NULL; +static u_int test_number = 0; +static test_onerror_func_t *test_onerror = NULL; +static void *onerror_ctx = NULL; +static const char *data_dir = NULL; +static char subtest_info[512]; +static int fast = 0; +static int slow = 0; + +int +main(int argc, char **argv) +{ + int ch; + + seed_rng(); +#ifdef WITH_OPENSSL + ERR_load_CRYPTO_strings(); +#endif + + /* Handle systems without __progname */ + if (__progname == NULL) { + __progname = strrchr(argv[0], '/'); + if (__progname == NULL || __progname[1] == '\0') + __progname = argv[0]; + else + __progname++; + if ((__progname = strdup(__progname)) == NULL) { + fprintf(stderr, "strdup failed\n"); + exit(1); + } + } + + while ((ch = getopt(argc, argv, "Ffvqd:")) != -1) { + switch (ch) { + case 'F': + slow = 1; + break; + case 'f': + fast = 1; + break; + case 'd': + data_dir = optarg; + break; + case 'q': + verbose_mode = 0; + quiet_mode = 1; + break; + case 'v': + verbose_mode = 1; + quiet_mode = 0; + break; + default: + fprintf(stderr, "Unrecognised command line option\n"); + fprintf(stderr, "Usage: %s [-v]\n", __progname); + exit(1); + } + } + setvbuf(stdout, NULL, _IONBF, 0); + if (!quiet_mode) + printf("%s: ", __progname); + if (verbose_mode) + printf("\n"); + + tests(); + + if (!quiet_mode) + printf(" %u tests ok\n", test_number); + return 0; +} + +int +test_is_verbose(void) +{ + return verbose_mode; +} + +int +test_is_quiet(void) +{ + return quiet_mode; +} + +int +test_is_fast(void) +{ + return fast; +} + +int +test_is_slow(void) +{ + return slow; +} + +const char * +test_data_file(const char *name) +{ + static char ret[PATH_MAX]; + + if (data_dir != NULL) + snprintf(ret, sizeof(ret), "%s/%s", data_dir, name); + else + strlcpy(ret, name, sizeof(ret)); + if (access(ret, F_OK) != 0) { + fprintf(stderr, "Cannot access data file %s: %s\n", + ret, strerror(errno)); + exit(1); + } + return ret; +} + +void +test_info(char *s, size_t len) +{ + snprintf(s, len, "In test %u: \"%s\"%s%s\n", test_number, + active_test_name == NULL ? "<none>" : active_test_name, + *subtest_info != '\0' ? " - " : "", subtest_info); +} + +static void +siginfo(int unused __attribute__((__unused__))) +{ + char buf[256]; + + test_info(buf, sizeof(buf)); + atomicio(vwrite, STDERR_FILENO, buf, strlen(buf)); +} + +void +test_start(const char *n) +{ + assert(active_test_name == NULL); + assert((active_test_name = strdup(n)) != NULL); + *subtest_info = '\0'; + if (verbose_mode) + printf("test %u - \"%s\": ", test_number, active_test_name); + test_number++; +#ifdef SIGINFO + signal(SIGINFO, siginfo); +#endif + signal(SIGUSR1, siginfo); +} + +void +set_onerror_func(test_onerror_func_t *f, void *ctx) +{ + test_onerror = f; + onerror_ctx = ctx; +} + +void +test_done(void) +{ + *subtest_info = '\0'; + assert(active_test_name != NULL); + free(active_test_name); + active_test_name = NULL; + if (verbose_mode) + printf("OK\n"); + else if (!quiet_mode) { + printf("."); + fflush(stdout); + } +} + +void +test_subtest_info(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + vsnprintf(subtest_info, sizeof(subtest_info), fmt, ap); + va_end(ap); +} + +void +ssl_err_check(const char *file, int line) +{ +#ifdef WITH_OPENSSL + long openssl_error = ERR_get_error(); + + if (openssl_error == 0) + return; + + fprintf(stderr, "\n%s:%d: uncaught OpenSSL error: %s", + file, line, ERR_error_string(openssl_error, NULL)); +#else /* WITH_OPENSSL */ + fprintf(stderr, "\n%s:%d: uncaught OpenSSL error ", + file, line); +#endif /* WITH_OPENSSL */ + abort(); +} + +static const char * +pred_name(enum test_predicate p) +{ + switch (p) { + case TEST_EQ: + return "EQ"; + case TEST_NE: + return "NE"; + case TEST_LT: + return "LT"; + case TEST_LE: + return "LE"; + case TEST_GT: + return "GT"; + case TEST_GE: + return "GE"; + default: + return "UNKNOWN"; + } +} + +static void +test_die(void) +{ + if (test_onerror != NULL) + test_onerror(onerror_ctx); + abort(); +} + +static void +test_header(const char *file, int line, const char *a1, const char *a2, + const char *name, enum test_predicate pred) +{ + fprintf(stderr, "\n%s:%d test #%u \"%s\"%s%s\n", + file, line, test_number, active_test_name, + *subtest_info != '\0' ? " - " : "", subtest_info); + fprintf(stderr, "ASSERT_%s_%s(%s%s%s) failed:\n", + name, pred_name(pred), a1, + a2 != NULL ? ", " : "", a2 != NULL ? a2 : ""); +} + +#ifdef WITH_OPENSSL +void +assert_bignum(const char *file, int line, const char *a1, const char *a2, + const BIGNUM *aa1, const BIGNUM *aa2, enum test_predicate pred) +{ + int r = BN_cmp(aa1, aa2); + + TEST_CHECK_INT(r, pred); + test_header(file, line, a1, a2, "BIGNUM", pred); + fprintf(stderr, "%12s = 0x%s\n", a1, BN_bn2hex(aa1)); + fprintf(stderr, "%12s = 0x%s\n", a2, BN_bn2hex(aa2)); + test_die(); +} +#endif + +void +assert_string(const char *file, int line, const char *a1, const char *a2, + const char *aa1, const char *aa2, enum test_predicate pred) +{ + int r; + + /* Verify pointers are not NULL */ + assert_ptr(file, line, a1, "NULL", aa1, NULL, TEST_NE); + assert_ptr(file, line, a2, "NULL", aa2, NULL, TEST_NE); + + r = strcmp(aa1, aa2); + TEST_CHECK_INT(r, pred); + test_header(file, line, a1, a2, "STRING", pred); + fprintf(stderr, "%12s = %s (len %zu)\n", a1, aa1, strlen(aa1)); + fprintf(stderr, "%12s = %s (len %zu)\n", a2, aa2, strlen(aa2)); + test_die(); +} + +static char * +tohex(const void *_s, size_t l) +{ + u_int8_t *s = (u_int8_t *)_s; + size_t i, j; + const char *hex = "0123456789abcdef"; + char *r = malloc((l * 2) + 1); + + assert(r != NULL); + for (i = j = 0; i < l; i++) { + r[j++] = hex[(s[i] >> 4) & 0xf]; + r[j++] = hex[s[i] & 0xf]; + } + r[j] = '\0'; + return r; +} + +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) +{ + int r; + char *aa1_tohex = NULL; + char *aa2_tohex = NULL; + + if (l == 0) + return; + /* If length is >0, then verify pointers are not NULL */ + assert_ptr(file, line, a1, "NULL", aa1, NULL, TEST_NE); + assert_ptr(file, line, a2, "NULL", aa2, NULL, TEST_NE); + + r = memcmp(aa1, aa2, l); + TEST_CHECK_INT(r, pred); + test_header(file, line, a1, a2, "STRING", pred); + aa1_tohex = tohex(aa1, MIN(l, 256)); + aa2_tohex = tohex(aa2, MIN(l, 256)); + fprintf(stderr, "%12s = %s (len %zu)\n", a1, aa1_tohex, l); + fprintf(stderr, "%12s = %s (len %zu)\n", a2, aa2_tohex, l); + free(aa1_tohex); + free(aa2_tohex); + test_die(); +} + +static int +memvalcmp(const u_int8_t *s, u_char v, size_t l, size_t *where) +{ + size_t i; + + for (i = 0; i < l; i++) { + if (s[i] != v) { + *where = i; + return 1; + } + } + return 0; +} + +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) +{ + size_t where = -1; + int r; + char tmp[64]; + char *aa1_tohex = NULL; + + if (l == 0) + return; + /* If length is >0, then verify the pointer is not NULL */ + assert_ptr(file, line, a1, "NULL", aa1, NULL, TEST_NE); + + r = memvalcmp(aa1, v, l, &where); + TEST_CHECK_INT(r, pred); + test_header(file, line, a1, NULL, "MEM_ZERO", pred); + aa1_tohex = tohex(aa1, MIN(l, 20)); + fprintf(stderr, "%20s = %s%s (len %zu)\n", a1, + aa1_tohex, l > 20 ? "..." : "", l); + free(aa1_tohex); + snprintf(tmp, sizeof(tmp), "(%s)[%zu]", a1, where); + fprintf(stderr, "%20s = 0x%02x (expected 0x%02x)\n", tmp, + ((u_char *)aa1)[where], v); + test_die(); +} + +void +assert_int(const char *file, int line, const char *a1, const char *a2, + int aa1, int aa2, enum test_predicate pred) +{ + TEST_CHECK(aa1, aa2, pred); + test_header(file, line, a1, a2, "INT", pred); + fprintf(stderr, "%12s = %d\n", a1, aa1); + fprintf(stderr, "%12s = %d\n", a2, aa2); + test_die(); +} + +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) +{ + TEST_CHECK(aa1, aa2, pred); + test_header(file, line, a1, a2, "SIZE_T", pred); + fprintf(stderr, "%12s = %zu\n", a1, aa1); + fprintf(stderr, "%12s = %zu\n", a2, aa2); + test_die(); +} + +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) +{ + TEST_CHECK(aa1, aa2, pred); + test_header(file, line, a1, a2, "U_INT", pred); + fprintf(stderr, "%12s = %u / 0x%x\n", a1, aa1, aa1); + fprintf(stderr, "%12s = %u / 0x%x\n", a2, aa2, aa2); + test_die(); +} + +void +assert_long(const char *file, int line, const char *a1, const char *a2, + long aa1, long aa2, enum test_predicate pred) +{ + TEST_CHECK(aa1, aa2, pred); + test_header(file, line, a1, a2, "LONG", pred); + fprintf(stderr, "%12s = %ld / 0x%lx\n", a1, aa1, aa1); + fprintf(stderr, "%12s = %ld / 0x%lx\n", a2, aa2, aa2); + test_die(); +} + +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) +{ + TEST_CHECK(aa1, aa2, pred); + test_header(file, line, a1, a2, "LONG LONG", pred); + fprintf(stderr, "%12s = %lld / 0x%llx\n", a1, aa1, aa1); + fprintf(stderr, "%12s = %lld / 0x%llx\n", a2, aa2, aa2); + test_die(); +} + +void +assert_char(const char *file, int line, const char *a1, const char *a2, + char aa1, char aa2, enum test_predicate pred) +{ + char buf[8]; + + TEST_CHECK(aa1, aa2, pred); + test_header(file, line, a1, a2, "CHAR", pred); + fprintf(stderr, "%12s = '%s' / 0x02%x\n", a1, + vis(buf, aa1, VIS_SAFE|VIS_NL|VIS_TAB|VIS_OCTAL, 0), aa1); + fprintf(stderr, "%12s = '%s' / 0x02%x\n", a1, + vis(buf, aa2, VIS_SAFE|VIS_NL|VIS_TAB|VIS_OCTAL, 0), aa2); + test_die(); +} + +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) +{ + TEST_CHECK(aa1, aa2, pred); + test_header(file, line, a1, a2, "U8", pred); + fprintf(stderr, "%12s = 0x%02x %u\n", a1, aa1, aa1); + fprintf(stderr, "%12s = 0x%02x %u\n", a2, aa2, aa2); + test_die(); +} + +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) +{ + TEST_CHECK(aa1, aa2, pred); + test_header(file, line, a1, a2, "U16", pred); + fprintf(stderr, "%12s = 0x%04x %u\n", a1, aa1, aa1); + fprintf(stderr, "%12s = 0x%04x %u\n", a2, aa2, aa2); + test_die(); +} + +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) +{ + TEST_CHECK(aa1, aa2, pred); + test_header(file, line, a1, a2, "U32", pred); + fprintf(stderr, "%12s = 0x%08x %u\n", a1, aa1, aa1); + fprintf(stderr, "%12s = 0x%08x %u\n", a2, aa2, aa2); + test_die(); +} + +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) +{ + TEST_CHECK(aa1, aa2, pred); + test_header(file, line, a1, a2, "U64", pred); + fprintf(stderr, "%12s = 0x%016llx %llu\n", a1, + (unsigned long long)aa1, (unsigned long long)aa1); + fprintf(stderr, "%12s = 0x%016llx %llu\n", a2, + (unsigned long long)aa2, (unsigned long long)aa2); + test_die(); +} + +void +assert_ptr(const char *file, int line, const char *a1, const char *a2, + const void *aa1, const void *aa2, enum test_predicate pred) +{ + TEST_CHECK(aa1, aa2, pred); + test_header(file, line, a1, a2, "PTR", pred); + fprintf(stderr, "%12s = %p\n", a1, aa1); + fprintf(stderr, "%12s = %p\n", a2, aa2); + test_die(); +} + diff --git a/regress/unittests/test_helper/test_helper.h b/regress/unittests/test_helper/test_helper.h new file mode 100644 index 0000000..6630220 --- /dev/null +++ b/regress/unittests/test_helper/test_helper.h @@ -0,0 +1,326 @@ +/* $OpenBSD: test_helper.h,v 1.9 2018/10/17 23:28:05 djm Exp $ */ +/* + * Copyright (c) 2011 Damien Miller <djm@mindrot.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* Utility functions/framework for regress tests */ + +#ifndef _TEST_HELPER_H +#define _TEST_HELPER_H + +#include "includes.h" + +#include <sys/types.h> +#ifdef HAVE_STDINT_H +# include <stdint.h> +#endif + +#ifdef WITH_OPENSSL +#include <openssl/bn.h> +#include <openssl/err.h> +#endif + +enum test_predicate { + TEST_EQ, TEST_NE, TEST_LT, TEST_LE, TEST_GT, TEST_GE +}; +typedef void (test_onerror_func_t)(void *); + +/* Supplied by test suite */ +void tests(void); + +const char *test_data_file(const char *name); +void test_start(const char *n); +void test_info(char *s, size_t len); +void set_onerror_func(test_onerror_func_t *f, void *ctx); +void test_done(void); +int test_is_verbose(void); +int test_is_quiet(void); +int test_is_fast(void); +int test_is_slow(void); +void test_subtest_info(const char *fmt, ...) + __attribute__((format(printf, 1, 2))); +void ssl_err_check(const char *file, int line); +#ifdef WITH_OPENSSL +void assert_bignum(const char *file, int line, + const char *a1, const char *a2, + const BIGNUM *aa1, const BIGNUM *aa2, enum test_predicate pred); +#endif +void assert_string(const char *file, int line, + const char *a1, const char *a2, + const char *aa1, const char *aa2, enum test_predicate pred); +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); +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); +void assert_int(const char *file, int line, + const char *a1, const char *a2, + int aa1, int aa2, enum test_predicate pred); +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); +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); +void assert_long(const char *file, int line, + const char *a1, const char *a2, + long aa1, long aa2, enum test_predicate pred); +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); +void assert_char(const char *file, int line, + const char *a1, const char *a2, + char aa1, char aa2, enum test_predicate pred); +void assert_ptr(const char *file, int line, + const char *a1, const char *a2, + const void *aa1, const void *aa2, enum test_predicate pred); +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); +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); +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); +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); + +#define TEST_START(n) test_start(n) +#define TEST_DONE() test_done() +#define TEST_ONERROR(f, c) set_onerror_func(f, c) +#define SSL_ERR_CHECK() ssl_err_check(__FILE__, __LINE__) + +#define ASSERT_BIGNUM_EQ(a1, a2) \ + assert_bignum(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ) +#define ASSERT_STRING_EQ(a1, a2) \ + assert_string(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ) +#define ASSERT_MEM_EQ(a1, a2, l) \ + assert_mem(__FILE__, __LINE__, #a1, #a2, a1, a2, l, TEST_EQ) +#define ASSERT_MEM_FILLED_EQ(a1, c, l) \ + assert_mem_filled(__FILE__, __LINE__, #a1, a1, c, l, TEST_EQ) +#define ASSERT_MEM_ZERO_EQ(a1, l) \ + assert_mem_filled(__FILE__, __LINE__, #a1, a1, '\0', l, TEST_EQ) +#define ASSERT_INT_EQ(a1, a2) \ + assert_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ) +#define ASSERT_SIZE_T_EQ(a1, a2) \ + assert_size_t(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ) +#define ASSERT_U_INT_EQ(a1, a2) \ + assert_u_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ) +#define ASSERT_LONG_EQ(a1, a2) \ + assert_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ) +#define ASSERT_LONG_LONG_EQ(a1, a2) \ + assert_long_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ) +#define ASSERT_CHAR_EQ(a1, a2) \ + assert_char(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ) +#define ASSERT_PTR_EQ(a1, a2) \ + assert_ptr(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ) +#define ASSERT_U8_EQ(a1, a2) \ + assert_u8(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ) +#define ASSERT_U16_EQ(a1, a2) \ + assert_u16(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ) +#define ASSERT_U32_EQ(a1, a2) \ + assert_u32(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ) +#define ASSERT_U64_EQ(a1, a2) \ + assert_u64(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ) + +#define ASSERT_BIGNUM_NE(a1, a2) \ + assert_bignum(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE) +#define ASSERT_STRING_NE(a1, a2) \ + assert_string(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE) +#define ASSERT_MEM_NE(a1, a2, l) \ + assert_mem(__FILE__, __LINE__, #a1, #a2, a1, a2, l, TEST_NE) +#define ASSERT_MEM_ZERO_NE(a1, l) \ + assert_mem_filled(__FILE__, __LINE__, #a1, a1, '\0', l, TEST_NE) +#define ASSERT_INT_NE(a1, a2) \ + assert_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE) +#define ASSERT_SIZE_T_NE(a1, a2) \ + assert_size_t(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE) +#define ASSERT_U_INT_NE(a1, a2) \ + assert_u_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE) +#define ASSERT_LONG_NE(a1, a2) \ + assert_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE) +#define ASSERT_LONG_LONG_NE(a1, a2) \ + assert_long_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE) +#define ASSERT_CHAR_NE(a1, a2) \ + assert_char(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE) +#define ASSERT_PTR_NE(a1, a2) \ + assert_ptr(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE) +#define ASSERT_U8_NE(a1, a2) \ + assert_u8(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE) +#define ASSERT_U16_NE(a1, a2) \ + assert_u16(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE) +#define ASSERT_U32_NE(a1, a2) \ + assert_u32(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE) +#define ASSERT_U64_NE(a1, a2) \ + assert_u64(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE) + +#define ASSERT_BIGNUM_LT(a1, a2) \ + assert_bignum(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT) +#define ASSERT_STRING_LT(a1, a2) \ + assert_string(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT) +#define ASSERT_MEM_LT(a1, a2, l) \ + assert_mem(__FILE__, __LINE__, #a1, #a2, a1, a2, l, TEST_LT) +#define ASSERT_INT_LT(a1, a2) \ + assert_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT) +#define ASSERT_SIZE_T_LT(a1, a2) \ + assert_size_t(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT) +#define ASSERT_U_INT_LT(a1, a2) \ + assert_u_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT) +#define ASSERT_LONG_LT(a1, a2) \ + assert_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT) +#define ASSERT_LONG_LONG_LT(a1, a2) \ + assert_long_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT) +#define ASSERT_CHAR_LT(a1, a2) \ + assert_char(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT) +#define ASSERT_PTR_LT(a1, a2) \ + assert_ptr(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT) +#define ASSERT_U8_LT(a1, a2) \ + assert_u8(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT) +#define ASSERT_U16_LT(a1, a2) \ + assert_u16(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT) +#define ASSERT_U32_LT(a1, a2) \ + assert_u32(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT) +#define ASSERT_U64_LT(a1, a2) \ + assert_u64(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT) + +#define ASSERT_BIGNUM_LE(a1, a2) \ + assert_bignum(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE) +#define ASSERT_STRING_LE(a1, a2) \ + assert_string(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE) +#define ASSERT_MEM_LE(a1, a2, l) \ + assert_mem(__FILE__, __LINE__, #a1, #a2, a1, a2, l, TEST_LE) +#define ASSERT_INT_LE(a1, a2) \ + assert_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE) +#define ASSERT_SIZE_T_LE(a1, a2) \ + assert_size_t(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE) +#define ASSERT_U_INT_LE(a1, a2) \ + assert_u_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE) +#define ASSERT_LONG_LE(a1, a2) \ + assert_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE) +#define ASSERT_LONG_LONG_LE(a1, a2) \ + assert_long_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE) +#define ASSERT_CHAR_LE(a1, a2) \ + assert_char(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE) +#define ASSERT_PTR_LE(a1, a2) \ + assert_ptr(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE) +#define ASSERT_U8_LE(a1, a2) \ + assert_u8(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE) +#define ASSERT_U16_LE(a1, a2) \ + assert_u16(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE) +#define ASSERT_U32_LE(a1, a2) \ + assert_u32(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE) +#define ASSERT_U64_LE(a1, a2) \ + assert_u64(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE) + +#define ASSERT_BIGNUM_GT(a1, a2) \ + assert_bignum(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT) +#define ASSERT_STRING_GT(a1, a2) \ + assert_string(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT) +#define ASSERT_MEM_GT(a1, a2, l) \ + assert_mem(__FILE__, __LINE__, #a1, #a2, a1, a2, l, TEST_GT) +#define ASSERT_INT_GT(a1, a2) \ + assert_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT) +#define ASSERT_SIZE_T_GT(a1, a2) \ + assert_size_t(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT) +#define ASSERT_U_INT_GT(a1, a2) \ + assert_u_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT) +#define ASSERT_LONG_GT(a1, a2) \ + assert_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT) +#define ASSERT_LONG_LONG_GT(a1, a2) \ + assert_long_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT) +#define ASSERT_CHAR_GT(a1, a2) \ + assert_char(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT) +#define ASSERT_PTR_GT(a1, a2) \ + assert_ptr(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT) +#define ASSERT_U8_GT(a1, a2) \ + assert_u8(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT) +#define ASSERT_U16_GT(a1, a2) \ + assert_u16(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT) +#define ASSERT_U32_GT(a1, a2) \ + assert_u32(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT) +#define ASSERT_U64_GT(a1, a2) \ + assert_u64(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT) + +#define ASSERT_BIGNUM_GE(a1, a2) \ + assert_bignum(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE) +#define ASSERT_STRING_GE(a1, a2) \ + assert_string(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE) +#define ASSERT_MEM_GE(a1, a2, l) \ + assert_mem(__FILE__, __LINE__, #a1, #a2, a1, a2, l, TEST_GE) +#define ASSERT_INT_GE(a1, a2) \ + assert_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE) +#define ASSERT_SIZE_T_GE(a1, a2) \ + assert_size_t(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE) +#define ASSERT_U_INT_GE(a1, a2) \ + assert_u_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE) +#define ASSERT_LONG_GE(a1, a2) \ + assert_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE) +#define ASSERT_LONG_LONG_GE(a1, a2) \ + assert_long_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE) +#define ASSERT_CHAR_GE(a1, a2) \ + assert_char(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE) +#define ASSERT_PTR_GE(a1, a2) \ + assert_ptr(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE) +#define ASSERT_U8_GE(a1, a2) \ + assert_u8(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE) +#define ASSERT_U16_GE(a1, a2) \ + assert_u16(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE) +#define ASSERT_U32_GE(a1, a2) \ + assert_u32(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE) +#define ASSERT_U64_GE(a1, a2) \ + assert_u64(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE) + +/* Fuzzing support */ + +struct fuzz; +#define FUZZ_1_BIT_FLIP 0x00000001 /* Flip one bit at a time */ +#define FUZZ_2_BIT_FLIP 0x00000002 /* Flip two bits at a time */ +#define FUZZ_1_BYTE_FLIP 0x00000004 /* Flip one byte at a time */ +#define FUZZ_2_BYTE_FLIP 0x00000008 /* Flip two bytes at a time */ +#define FUZZ_TRUNCATE_START 0x00000010 /* Truncate from beginning */ +#define FUZZ_TRUNCATE_END 0x00000020 /* Truncate from end */ +#define FUZZ_BASE64 0x00000040 /* Try all base64 chars */ +#define FUZZ_MAX FUZZ_BASE64 + +/* Start fuzzing a blob of data with selected strategies (bitmask) */ +struct fuzz *fuzz_begin(u_int strategies, const void *p, size_t l); + +/* Free a fuzz context */ +void fuzz_cleanup(struct fuzz *fuzz); + +/* Prepare the next fuzz case in the series */ +void fuzz_next(struct fuzz *fuzz); + +/* + * Check whether this fuzz case is identical to the original + * This is slow, but useful if the caller needs to ensure that all tests + * generated change the input (e.g. when fuzzing signatures). + */ +int fuzz_matches_original(struct fuzz *fuzz); + +/* Determine whether the current fuzz sequence is exhausted (nonzero = yes) */ +int fuzz_done(struct fuzz *fuzz); + +/* Return the length and a pointer to the current fuzzed case */ +size_t fuzz_len(struct fuzz *fuzz); +u_char *fuzz_ptr(struct fuzz *fuzz); + +/* Dump the current fuzz case to stderr */ +void fuzz_dump(struct fuzz *fuzz); + +#endif /* _TEST_HELPER_H */ |