aboutsummaryrefslogtreecommitdiffstats
path: root/common.h
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--common.h162
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