#include #include #include #include #include "mmh3.h" typedef struct { const char *name; const void *data; size_t len; uint64_t seed; uint64_t expected0; uint64_t expected1; } test_vector; static int test_mmh3_128_vector(const test_vector *test) { uint64_t out[2] = {0, 0}; mmh3_128( test->data, test->len, test->seed, out ); if (out[0] != test->expected0 || out[1] != test->expected1) { fprintf( stderr, "FAIL: %s\n" " expected: %016" PRIx64 " %016" PRIx64 "\n" " actual: %016" PRIx64 " %016" PRIx64 "\n", test->name, test->expected0, test->expected1, out[0], out[1] ); return 1; } printf("PASS: %s\n", test->name); return 0; } static int test_mmh3_128_unaligned(void) { static const char text[] = "The quick brown fox jumps over the lazy dog"; uint8_t buffer[sizeof(text) + 1]; /* * Force the input to begin at an address offset by one byte. * This catches implementations that incorrectly cast arbitrary * byte pointers to uint64_t * and perform aligned word reads. */ memcpy(buffer + 1, text, sizeof(text) - 1); const test_vector test = { .name = "x64_128 unaligned input", .data = buffer + 1, .len = sizeof(text) - 1, .seed = 0, .expected0 = UINT64_C(0xe34bbc7bbc071b6c), .expected1 = UINT64_C(0x7a433ca9c49a9347), }; return test_mmh3_128_vector(&test); } int main(void) { static const char empty[] = ""; static const char foo[] = "foo"; static const char hello[] = "hello"; static const char block16[] = "0123456789abcdef"; static const char block17[] = "0123456789abcdefg"; static const char quickfox[] = "The quick brown fox jumps over the lazy dog"; static const test_vector tests[] = { { .name = "x64_128 empty, seed 0", .data = empty, .len = 0, .seed = 0, .expected0 = UINT64_C(0x0000000000000000), .expected1 = UINT64_C(0x0000000000000000), }, { .name = "x64_128 foo, seed 0", .data = foo, .len = sizeof(foo) - 1, .seed = 0, .expected0 = UINT64_C(0xe271865701f54561), .expected1 = UINT64_C(0x7eaf87e42bba7d87), }, { .name = "x64_128 hello, seed 0", .data = hello, .len = sizeof(hello) - 1, .seed = 0, .expected0 = UINT64_C(0xcbd8a7b341bd9b02), .expected1 = UINT64_C(0x5b1e906a48ae1d19), }, { .name = "x64_128 exactly 16 bytes", .data = block16, .len = sizeof(block16) - 1, .seed = 0, .expected0 = UINT64_C(0x4be06d94cf4ad1a7), .expected1 = UINT64_C(0x87c35b5c63a708da), }, { .name = "x64_128 17 bytes", .data = block17, .len = sizeof(block17) - 1, .seed = 0, .expected0 = UINT64_C(0x8e32612daa45f9de), .expected1 = UINT64_C(0x0800f4c206c372ee), }, { .name = "x64_128 quick fox, seed 0", .data = quickfox, .len = sizeof(quickfox) - 1, .seed = 0, .expected0 = UINT64_C(0xe34bbc7bbc071b6c), .expected1 = UINT64_C(0x7a433ca9c49a9347), }, { .name = "x64_128 foo, seed 42", .data = foo, .len = sizeof(foo) - 1, .seed = 42, .expected0 = UINT64_C(0xf4569d51637053f2), .expected1 = UINT64_C(0xa279b5d8eeb09aa9), }, }; int failures = 0; for (size_t i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { failures += test_mmh3_128_vector(&tests[i]); } failures += test_mmh3_128_unaligned(); if (failures != 0) { fprintf( stderr, "\n%d test%s failed\n", failures, failures == 1 ? "" : "s" ); return 1; } printf("\nAll mmh3 tests passed.\n"); return 0; }