diff options
Diffstat (limited to 'common.h')
-rw-r--r-- | common.h | 162 |
1 files changed, 162 insertions, 0 deletions
diff --git a/common.h b/common.h new file mode 100644 index 0000000..e79d6c8 --- /dev/null +++ b/common.h @@ -0,0 +1,162 @@ +/* See LICENSE file for copyright and license details. */ +#include "libhashsum.h" +#include <errno.h> +#include <string.h> + +#ifdef TEST +# include <stdlib.h> +# include <stdio.h> + +struct testcase { + size_t input_repeat; + unsigned extra_bits; + const char *input; + const char *output; +}; + +static void +hex(char *out, const unsigned char *in, size_t n) +{ + for (; n--; in++) { + *out++ = "0123456789abcdef"[(*in >> 4) & 15]; + *out++ = "0123456789abcdef"[(*in >> 0) & 15]; + } + *out = '\0'; +} + +static char * +escape(const char *s, size_t n) +{ + char *ret, *p; + + ret = malloc(n * 4U + 1U); + if (!ret) { + perror("malloc"); + exit(2); + } + + for (p = ret; n--; s++) { + if (*s == '"' || *s == '\\') { + *p++ = '\\'; + *p++ = *s; + } else if (*s == '\n') { + *p++ = '\\'; + *p++ = 'n'; + } else if (*s < ' ' || *s >= 127) { + *p++ = '\\'; + *p++ = 'x'; + *p++ = "0123456789abcdef"[(*s >> 4) & 15]; + *p++ = "0123456789abcdef"[(*s >> 0) & 15]; + } else { + *p++ = *s; + } + } + *p = '\0'; + + return ret; +} + +static int +run_tests(const char *name, enum libhashsum_algorithm algorithm, size_t hash_size, + struct testcase *testcases, size_t ntestcases, char hexsum[]) +{ + struct libhashsum_hasher hasher; + char *input, *p, bitstr[sizeof(" + b\"1234567\"")]; + unsigned char extra_bit; + int ok = 1, caseok; + size_t i, j, input_string_len, input_total_len, input_size; + size_t bits; + for (i = 0; i < ntestcases; i++) { + if (libhashsum_init_hasher(&hasher, algorithm)) { + perror("libhashsum_init_hasher"); + return 2; + } + if (hasher.algorithm != algorithm) { + fprintf(stderr, "libhashsum_init_hasher returned unexpected value in .algorithm\n"); + return 2; + } + if (hasher.hash_size != hash_size) { + fprintf(stderr, "libhashsum_init_hasher returned unexpected value in .hash_size\n"); + return 2; + } + if (hasher.hash_output) { + fprintf(stderr, "libhashsum_init_hasher returned non-NULL pointer in .hash_output\n"); + return 2; + } + if (!hasher.process) { + fprintf(stderr, "libhashsum_init_hasher returned NULL pointer in .process\n"); + return 2; + } + if (!hasher.finalise_const) { + fprintf(stderr, "libhashsum_init_hasher returned NULL pointer in .finalise_const\n"); + return 2; + } + if (!hasher.finalise) { + fprintf(stderr, "libhashsum_init_hasher returned NULL pointer in .finalise\n"); + return 2; + } + input_string_len = strlen(testcases[i].input); + bits = testcases[i].extra_bits; + if (bits) { + if (input_string_len < (bits + 7U) / 8U) + input_string_len = (bits + 7U) / 8U; + bits %= 8U; + if (bits) + input_string_len -= 1U; + } + input_total_len = testcases[i].input_repeat * input_string_len; + input_size = input_total_len + hasher.input_block_size + 1U; + p = input = malloc(input_size); + if (!input) { + perror("malloc"); + return 2; + } + for (j = 0; j < testcases[i].input_repeat; j++) { + p = memcpy(p, testcases[i].input, input_string_len); + p = &p[input_string_len]; + } + if (hasher.finalise(&hasher, input, input_total_len, (unsigned)bits, input_size)) { + perror("hasher.finalise"); + return 2; + } + if (!hasher.hash_output) { + fprintf(stderr, "hasher.finalise did not set hasher.hash_output\n"); + return 2; + } + free(input); + hex(hexsum, hasher.hash_output, hasher.hash_size); + ok &= caseok = !testcases[i].output || !strcmp(hexsum, testcases[i].output); + input = escape(testcases[i].input, input_string_len); + bitstr[0] = '\0'; + if (bits) { + extra_bit = (unsigned char)testcases[i].input[input_string_len]; + p = bitstr; + *p++ = ' '; + *p++ = '+'; + *p++ = ' '; + *p++ = 'b'; + *p++ = '"'; + while (bits--) { + *p++ = "01"[(extra_bit >> 7) & 1U]; + extra_bit <<= 1; + } + *p++ = '"'; + *p = '\0'; + } + if (testcases[i].input_repeat == 1) + printf("[\033[1;%s\033[m] %s(\"%s\"%s) = %s\n", + caseok ? "32mPASS" : "31mFAIL", name, input, bitstr, hexsum); + else + printf("[\033[1;%s\033[m] %s(%zu * \"%s\"%s) = %s\n", + caseok ? "32mPASS" : "31mFAIL", name, testcases[i].input_repeat, input, bitstr, hexsum); + free(input); + } + return !ok; +} + +#define TEST_MAIN(NAME, ID)\ + char hexsum[LIBHASHSUM_##ID##_HASH_SIZE * 2 + 1];\ + return run_tests(NAME, LIBHASHSUM_##ID, LIBHASHSUM_##ID##_HASH_SIZE,\ + testcases, sizeof(testcases) / sizeof(*testcases), hexsum) + +#endif |