Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Test cases for <linux/hash.h> and <linux/stringhash.h>
0004  * This just verifies that various ways of computing a hash
0005  * produce the same thing and, for cases where a k-bit hash
0006  * value is requested, is of the requested size.
0007  *
0008  * We fill a buffer with a 255-byte null-terminated string,
0009  * and use both full_name_hash() and hashlen_string() to hash the
0010  * substrings from i to j, where 0 <= i < j < 256.
0011  *
0012  * The returned values are used to check that __hash_32() and
0013  * __hash_32_generic() compute the same thing.  Likewise hash_32()
0014  * and hash_64().
0015  */
0016 
0017 #include <linux/compiler.h>
0018 #include <linux/types.h>
0019 #include <linux/module.h>
0020 #include <linux/hash.h>
0021 #include <linux/stringhash.h>
0022 #include <kunit/test.h>
0023 
0024 /* 32-bit XORSHIFT generator.  Seed must not be zero. */
0025 static u32 __attribute_const__
0026 xorshift(u32 seed)
0027 {
0028     seed ^= seed << 13;
0029     seed ^= seed >> 17;
0030     seed ^= seed << 5;
0031     return seed;
0032 }
0033 
0034 /* Given a non-zero x, returns a non-zero byte. */
0035 static u8 __attribute_const__
0036 mod255(u32 x)
0037 {
0038     x = (x & 0xffff) + (x >> 16);   /* 1 <= x <= 0x1fffe */
0039     x = (x & 0xff) + (x >> 8);  /* 1 <= x <= 0x2fd */
0040     x = (x & 0xff) + (x >> 8);  /* 1 <= x <= 0x100 */
0041     x = (x & 0xff) + (x >> 8);  /* 1 <= x <= 0xff */
0042     return x;
0043 }
0044 
0045 /* Fill the buffer with non-zero bytes. */
0046 static void fill_buf(char *buf, size_t len, u32 seed)
0047 {
0048     size_t i;
0049 
0050     for (i = 0; i < len; i++) {
0051         seed = xorshift(seed);
0052         buf[i] = mod255(seed);
0053     }
0054 }
0055 
0056 /* Holds most testing variables for the int test. */
0057 struct test_hash_params {
0058         /* Pointer to integer to be hashed. */
0059     unsigned long long *h64;
0060         /* Low 32-bits of integer to be hashed. */
0061     u32 h0;
0062         /* Arch-specific hash result. */
0063     u32 h1;
0064         /* Generic hash result. */
0065     u32 h2;
0066         /* ORed hashes of given size (in bits). */
0067     u32 (*hash_or)[33];
0068 };
0069 
0070 #ifdef HAVE_ARCH__HASH_32
0071 static void
0072 test_int__hash_32(struct kunit *test, struct test_hash_params *params)
0073 {
0074     params->hash_or[1][0] |= params->h2 = __hash_32_generic(params->h0);
0075 #if HAVE_ARCH__HASH_32 == 1
0076     KUNIT_EXPECT_EQ_MSG(test, params->h1, params->h2,
0077                 "__hash_32(%#x) = %#x != __hash_32_generic() = %#x",
0078                 params->h0, params->h1, params->h2);
0079 #endif
0080 }
0081 #endif
0082 
0083 #ifdef HAVE_ARCH_HASH_64
0084 static void
0085 test_int_hash_64(struct kunit *test, struct test_hash_params *params, u32 const *m, int *k)
0086 {
0087     params->h2 = hash_64_generic(*params->h64, *k);
0088 #if HAVE_ARCH_HASH_64 == 1
0089     KUNIT_EXPECT_EQ_MSG(test, params->h1, params->h2,
0090                 "hash_64(%#llx, %d) = %#x != hash_64_generic() = %#x",
0091                 *params->h64, *k, params->h1, params->h2);
0092 #else
0093     KUNIT_EXPECT_LE_MSG(test, params->h1, params->h2,
0094                 "hash_64_generic(%#llx, %d) = %#x > %#x",
0095                 *params->h64, *k, params->h1, *m);
0096 #endif
0097 }
0098 #endif
0099 
0100 /*
0101  * Test the various integer hash functions.  h64 (or its low-order bits)
0102  * is the integer to hash.  hash_or accumulates the OR of the hash values,
0103  * which are later checked to see that they cover all the requested bits.
0104  *
0105  * Because these functions (as opposed to the string hashes) are all
0106  * inline, the code being tested is actually in the module, and you can
0107  * recompile and re-test the module without rebooting.
0108  */
0109 static void
0110 test_int_hash(struct kunit *test, unsigned long long h64, u32 hash_or[2][33])
0111 {
0112     int k;
0113     struct test_hash_params params = { &h64, (u32)h64, 0, 0, hash_or };
0114 
0115     /* Test __hash32 */
0116     hash_or[0][0] |= params.h1 = __hash_32(params.h0);
0117 #ifdef HAVE_ARCH__HASH_32
0118     test_int__hash_32(test, &params);
0119 #endif
0120 
0121     /* Test k = 1..32 bits */
0122     for (k = 1; k <= 32; k++) {
0123         u32 const m = ((u32)2 << (k-1)) - 1;    /* Low k bits set */
0124 
0125         /* Test hash_32 */
0126         hash_or[0][k] |= params.h1 = hash_32(params.h0, k);
0127         KUNIT_EXPECT_LE_MSG(test, params.h1, m,
0128                     "hash_32(%#x, %d) = %#x > %#x",
0129                     params.h0, k, params.h1, m);
0130 
0131         /* Test hash_64 */
0132         hash_or[1][k] |= params.h1 = hash_64(h64, k);
0133         KUNIT_EXPECT_LE_MSG(test, params.h1, m,
0134                     "hash_64(%#llx, %d) = %#x > %#x",
0135                     h64, k, params.h1, m);
0136 #ifdef HAVE_ARCH_HASH_64
0137         test_int_hash_64(test, &params, &m, &k);
0138 #endif
0139     }
0140 }
0141 
0142 #define SIZE 256    /* Run time is cubic in SIZE */
0143 
0144 static void test_string_or(struct kunit *test)
0145 {
0146     char buf[SIZE+1];
0147     u32 string_or = 0;
0148     int i, j;
0149 
0150     fill_buf(buf, SIZE, 1);
0151 
0152     /* Test every possible non-empty substring in the buffer. */
0153     for (j = SIZE; j > 0; --j) {
0154         buf[j] = '\0';
0155 
0156         for (i = 0; i <= j; i++) {
0157             u32 h0 = full_name_hash(buf+i, buf+i, j-i);
0158 
0159             string_or |= h0;
0160         } /* i */
0161     } /* j */
0162 
0163     /* The OR of all the hash values should cover all the bits */
0164     KUNIT_EXPECT_EQ_MSG(test, string_or, -1u,
0165                 "OR of all string hash results = %#x != %#x",
0166                 string_or, -1u);
0167 }
0168 
0169 static void test_hash_or(struct kunit *test)
0170 {
0171     char buf[SIZE+1];
0172     u32 hash_or[2][33] = { { 0, } };
0173     unsigned long long h64 = 0;
0174     int i, j;
0175 
0176     fill_buf(buf, SIZE, 1);
0177 
0178     /* Test every possible non-empty substring in the buffer. */
0179     for (j = SIZE; j > 0; --j) {
0180         buf[j] = '\0';
0181 
0182         for (i = 0; i <= j; i++) {
0183             u64 hashlen = hashlen_string(buf+i, buf+i);
0184             u32 h0 = full_name_hash(buf+i, buf+i, j-i);
0185 
0186             /* Check that hashlen_string gets the length right */
0187             KUNIT_EXPECT_EQ_MSG(test, hashlen_len(hashlen), j-i,
0188                         "hashlen_string(%d..%d) returned length %u, expected %d",
0189                         i, j, hashlen_len(hashlen), j-i);
0190             /* Check that the hashes match */
0191             KUNIT_EXPECT_EQ_MSG(test, hashlen_hash(hashlen), h0,
0192                         "hashlen_string(%d..%d) = %08x != full_name_hash() = %08x",
0193                         i, j, hashlen_hash(hashlen), h0);
0194 
0195             h64 = h64 << 32 | h0;   /* For use with hash_64 */
0196             test_int_hash(test, h64, hash_or);
0197         } /* i */
0198     } /* j */
0199 
0200     KUNIT_EXPECT_EQ_MSG(test, hash_or[0][0], -1u,
0201                 "OR of all __hash_32 results = %#x != %#x",
0202                 hash_or[0][0], -1u);
0203 #ifdef HAVE_ARCH__HASH_32
0204 #if HAVE_ARCH__HASH_32 != 1 /* Test is pointless if results match */
0205     KUNIT_EXPECT_EQ_MSG(test, hash_or[1][0], -1u,
0206                 "OR of all __hash_32_generic results = %#x != %#x",
0207                 hash_or[1][0], -1u);
0208 #endif
0209 #endif
0210 
0211     /* Likewise for all the i-bit hash values */
0212     for (i = 1; i <= 32; i++) {
0213         u32 const m = ((u32)2 << (i-1)) - 1;    /* Low i bits set */
0214 
0215         KUNIT_EXPECT_EQ_MSG(test, hash_or[0][i], m,
0216                     "OR of all hash_32(%d) results = %#x (%#x expected)",
0217                     i, hash_or[0][i], m);
0218         KUNIT_EXPECT_EQ_MSG(test, hash_or[1][i], m,
0219                     "OR of all hash_64(%d) results = %#x (%#x expected)",
0220                     i, hash_or[1][i], m);
0221     }
0222 }
0223 
0224 static struct kunit_case hash_test_cases[] __refdata = {
0225     KUNIT_CASE(test_string_or),
0226     KUNIT_CASE(test_hash_or),
0227     {}
0228 };
0229 
0230 static struct kunit_suite hash_test_suite = {
0231     .name = "hash",
0232     .test_cases = hash_test_cases,
0233 };
0234 
0235 
0236 kunit_test_suite(hash_test_suite);
0237 
0238 MODULE_LICENSE("GPL");