LCOV - code coverage report
Current view: top level - cmdline - selftest.c (source / functions) Hit Total Coverage
Test: lcov.info Lines: 147 148 99.3 %
Date: 2026-04-29 15:04:44 Functions: 9 9 100.0 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-3.0-or-later
       2             : // Copyright (C) 2011 Andrea Mazzoleni
       3             : 
       4             : #include "portable.h"
       5             : 
       6             : #include "snapraid.h"
       7             : #include "util.h"
       8             : #include "raid/raid.h"
       9             : #include "raid/cpu.h"
      10             : #include "raid/combo.h"
      11             : #include "raid/internal.h"
      12             : #include "raid/test.h"
      13             : #include "elem.h"
      14             : #include "state.h"
      15             : #include "support.h"
      16             : #include "tommyds/tommyhash.h"
      17             : #include "tommyds/tommyarray.h"
      18             : #include "tommyds/tommyarrayblkof.h"
      19             : #include "tommyds/tommyhashdyn.h"
      20             : 
      21             : struct hash32_test_vector {
      22             :         const char* data;
      23             :         int len;
      24             :         uint32_t digest;
      25             :         uint32_t seed;
      26             : };
      27             : 
      28             : struct strhash32_test_vector {
      29             :         char* data;
      30             :         uint32_t digest;
      31             :         uint32_t seed;
      32             : };
      33             : 
      34             : struct hash64_test_vector {
      35             :         const char* data;
      36             :         int len;
      37             :         uint64_t digest;
      38             :         uint64_t seed;
      39             : };
      40             : 
      41             : struct hash_test_vector {
      42             :         const char* data;
      43             :         int len;
      44             :         unsigned char digest[HASH_MAX];
      45             :         unsigned char seed[HASH_MAX];
      46             : };
      47             : 
      48             : /**
      49             :  * Test vectors for tommy_hash32
      50             :  */
      51             : static struct hash32_test_vector TEST_HASH32[] = {
      52             :         { "", 0, 0x8614384c, 0xa766795d },
      53             :         { "a", 1, 0x12c16c36, 0xa766795d },
      54             :         { "abc", 3, 0xc58e8af5, 0xa766795d },
      55             :         { "message digest", 14, 0x006b32f1, 0xa766795d },
      56             :         { "abcdefghijklmnopqrstuvwxyz", 26, 0x7e6fcfe0, 0xa766795d },
      57             :         { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", 62, 0x8604adf8, 0xa766795d },
      58             :         { "The quick brown fox jumps over the lazy dog", 43, 0xdeba3d3a, 0xa766795d },
      59             :         { "\x00", 1, 0x4a7d1c33, 0xa766795d },
      60             :         { "\x16\x27", 2, 0x8b50899b, 0xa766795d },
      61             :         { "\xe2\x56\xb4", 3, 0x60406493, 0xa766795d },
      62             :         { "\xc9\x4d\x9c\xda", 4, 0xa049144a, 0xa766795d },
      63             :         { "\x79\xf1\x29\x69\x5d", 5, 0x4da2c2f1, 0xa766795d },
      64             :         { "\x00\x7e\xdf\x1e\x31\x1c", 6, 0x59de30cf, 0xa766795d },
      65             :         { "\x2a\x4c\xe1\xff\x9e\x6f\x53", 7, 0x219e149c, 0xa766795d },
      66             :         { "\xba\x02\xab\x18\x30\xc5\x0e\x8a", 8, 0x25067520, 0xa766795d },
      67             :         { "\xec\x4e\x7a\x72\x1e\x71\x2a\xc9\x33", 9, 0xa1f368d8, 0xa766795d },
      68             :         { "\xfd\xe2\x9c\x0f\x72\xb7\x08\xea\xd0\x78", 10, 0x805fc63d, 0xa766795d },
      69             :         { "\x65\xc4\x8a\xb8\x80\x86\x9a\x79\x00\xb7\xae", 11, 0x7f75dd0f, 0xa766795d },
      70             :         { "\x77\xe9\xd7\x80\x0e\x3f\x5c\x43\xc8\xc2\x46\x39", 12, 0xb9154382, 0xa766795d },
      71             :         { 0, 0, 0, 0 }
      72             : };
      73             : 
      74             : /**
      75             :  * Test vectors for tommy_strhash32
      76             :  */
      77             : struct strhash32_test_vector TEST_STRHASH32[] = {
      78             :         { "", 0x0af1416d, 0xa766795d },
      79             :         { "a", 0x68fa0f3f, 0xa766795d },
      80             :         { "abc", 0xfc68ffc5, 0xa766795d },
      81             :         { "message digest", 0x08477b63, 0xa766795d },
      82             :         { "abcdefghijklmnopqrstuvwxyz", 0x5b9c25e5, 0xa766795d },
      83             :         { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", 0x1e530ce7, 0xa766795d },
      84             :         { "The quick brown fox jumps over the lazy dog", 0xaf93eefe, 0xa766795d },
      85             :         { "\xff", 0xfc88801b, 0xa766795d },
      86             :         { "\x16\x27", 0xcd7216db, 0xa766795d },
      87             :         { "\xe2\x56\xb4", 0x05f98d02, 0xa766795d },
      88             :         { "\xc9\x4d\x9c\xda", 0xf65206f8, 0xa766795d },
      89             :         { "\x79\xf1\x29\x69\x5d", 0x72bd6bda, 0xa766795d },
      90             :         { "\xff\x7e\xdf\x1e\x31\x1c", 0x57dfb9b4, 0xa766795d },
      91             :         { "\x2a\x4c\xe1\xff\x9e\x6f\x53", 0x499ff634, 0xa766795d },
      92             :         { "\xba\x02\xab\x18\x30\xc5\x0e\x8a", 0xe896b7ce, 0xa766795d },
      93             :         { "\xec\x4e\x7a\x72\x1e\x71\x2a\xc9\x33", 0xfe3939f0, 0xa766795d },
      94             :         { "\xfd\xe2\x9c\x0f\x72\xb7\x08\xea\xd0\x78", 0x4351d482, 0xa766795d },
      95             :         { "\x65\xc4\x8a\xb8\x80\x86\x9a\x79\xff\xb7\xae", 0x88e92135, 0xa766795d },
      96             :         { "\x77\xe9\xd7\x80\x0e\x3f\x5c\x43\xc8\xc2\x46\x39", 0x01109c16, 0xa766795d },
      97             :         { "\x87\xd8\x61\x61\x4c\x89\x17\x4e\xa1\xa4\xef\x13\xa9", 0xbcb050dc, 0xa766795d },
      98             :         { "\xfe\xa6\x5b\xc2\xda\xe8\x95\xd4\x64\xab\x4c\x39\x58\x29", 0xbe5e1fd5, 0xa766795d },
      99             :         { "\x94\x49\xc0\x78\xa0\x80\xda\xc7\x71\x4e\x17\x37\xa9\x7c\x40", 0x70d8c97f, 0xa766795d },
     100             :         { "\x53\x7e\x36\xb4\x2e\xc9\xb9\xcc\x18\x3e\x9a\x5f\xfc\xb7\xb0\x61", 0x957440a9, 0xa766795d },
     101             :         { 0, 0, 0 }
     102             : };
     103             : 
     104             : /**
     105             :  * Test vectors for tommy_hash64
     106             :  */
     107             : static struct hash64_test_vector TEST_HASH64[] = {
     108             :         { "", 0, 0x8614384cb5165fbfULL, 0x2f022773a766795dULL },
     109             :         { "a", 1, 0x1a2e0298a8e94a3dULL, 0x2f022773a766795dULL },
     110             :         { "abc", 3, 0x7555796b7a7d21ebULL, 0x2f022773a766795dULL },
     111             :         { "message digest", 14, 0x9411a57d04b92fb4ULL, 0x2f022773a766795dULL },
     112             :         { "abcdefghijklmnopqrstuvwxyz", 26, 0x3ca3f8d2b4e69832ULL, 0x2f022773a766795dULL },
     113             :         { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", 62, 0x6dae542ba0015a4dULL, 0x2f022773a766795dULL },
     114             :         { "The quick brown fox jumps over the lazy dog", 43, 0xe06d8cbb3d2ea1a6ULL, 0x2f022773a766795dULL },
     115             :         { "\x00", 1, 0x201e664fb5f2c021ULL, 0x2f022773a766795dULL },
     116             :         { "\x16\x27", 2, 0xef42fa8032c4b775ULL, 0x2f022773a766795dULL },
     117             :         { "\xe2\x56\xb4", 3, 0x6e6c498a6688466cULL, 0x2f022773a766795dULL },
     118             :         { "\xc9\x4d\x9c\xda", 4, 0x5195005419905423ULL, 0x2f022773a766795dULL },
     119             :         { "\x79\xf1\x29\x69\x5d", 5, 0x221235b48afee7c1ULL, 0x2f022773a766795dULL },
     120             :         { "\x00\x7e\xdf\x1e\x31\x1c", 6, 0x1b1f18b9266f095bULL, 0x2f022773a766795dULL },
     121             :         { "\x2a\x4c\xe1\xff\x9e\x6f\x53", 7, 0x2cbafa8e741d49caULL, 0x2f022773a766795dULL },
     122             :         { "\xba\x02\xab\x18\x30\xc5\x0e\x8a", 8, 0x4677f04c06e0758dULL, 0x2f022773a766795dULL },
     123             :         { "\xec\x4e\x7a\x72\x1e\x71\x2a\xc9\x33", 9, 0x5afe09e8214e2163ULL, 0x2f022773a766795dULL },
     124             :         { "\xfd\xe2\x9c\x0f\x72\xb7\x08\xea\xd0\x78", 10, 0x115b6276d209fab6ULL, 0x2f022773a766795dULL },
     125             :         { "\x65\xc4\x8a\xb8\x80\x86\x9a\x79\x00\xb7\xae", 11, 0xd0636d2f01cf3a3eULL, 0x2f022773a766795dULL },
     126             :         { "\x77\xe9\xd7\x80\x0e\x3f\x5c\x43\xc8\xc2\x46\x39", 12, 0x6d259f5fef74f93eULL, 0x2f022773a766795dULL },
     127             :         { 0, 0, 0, 0 }
     128             : };
     129             : 
     130             : /**
     131             :  * Test vectors for MurmorHash3_x86_128
     132             :  */
     133             : static struct hash_test_vector TEST_MURMUR3[] = {
     134             : #include "murmur3test.c"
     135             :         { 0, 0, { 0 }, { 0 } }
     136             : };
     137             : 
     138             : /**
     139             :  * Test vectors for SpookyHash_128
     140             :  */
     141             : static struct hash_test_vector TEST_SPOOKY2[] = {
     142             : #include "spooky2test.c"
     143             :         { 0, 0, { 0 }, { 0 } }
     144             : };
     145             : 
     146             : /**
     147             :  * Test vectors for MetroHash_128_1
     148             :  */
     149             : static struct hash_test_vector TEST_METRO[] = {
     150             : #include "metrotest.c"
     151             :         { 0, 0, { 0 }, { 0 } }
     152             : };
     153             : 
     154             : /**
     155             :  * Test vectors for MuseAirLoong
     156             :  */
     157             : static struct hash_test_vector TEST_MUSEAIR[] = {
     158             : #include "museairtest.c"
     159             :         { 0, 0, { 0 }, { 0 } }
     160             : };
     161             : 
     162             : #define HASH_TEST_MAX 512 /* tests are never longer than 512 bytes */
     163             : 
     164           1 : static void test_hash(void)
     165             : {
     166             :         unsigned i;
     167             :         unsigned char* seed_aligned;
     168             :         void* seed_alloc;
     169             :         unsigned char* buffer_aligned;
     170             :         void* buffer_alloc;
     171             : 
     172           1 :         seed_aligned = malloc_nofail_align(HASH_MAX, &seed_alloc);
     173           1 :         buffer_aligned = malloc_nofail_align(HASH_TEST_MAX, &buffer_alloc);
     174             : 
     175          20 :         for (i = 0; TEST_HASH32[i].data; ++i) {
     176             :                 uint32_t digest;
     177          19 :                 memcpy(buffer_aligned, TEST_HASH32[i].data, TEST_HASH32[i].len);
     178          19 :                 digest = tommy_hash_u32(TEST_HASH32[i].seed, buffer_aligned, TEST_HASH32[i].len);
     179          19 :                 if (digest != TEST_HASH32[i].digest) {
     180             :                         /* LCOV_EXCL_START */
     181             :                         log_fatal(EINTERNAL, "Failed hash32 test\n");
     182             :                         exit(EXIT_FAILURE);
     183             :                         /* LCOV_EXCL_STOP */
     184             :                 }
     185             :         }
     186             : 
     187          24 :         for (i = 0; TEST_STRHASH32[i].data; ++i) {
     188             :                 uint32_t digest;
     189          23 :                 memcpy(buffer_aligned, TEST_STRHASH32[i].data, strlen(TEST_STRHASH32[i].data) + 1);
     190          23 :                 digest = tommy_strhash_u32(TEST_STRHASH32[i].seed, buffer_aligned);
     191          23 :                 if (digest != TEST_STRHASH32[i].digest) {
     192             :                         /* LCOV_EXCL_START */
     193             :                         log_fatal(EINTERNAL, "Failed strhash32 test\n");
     194             :                         exit(EXIT_FAILURE);
     195             :                         /* LCOV_EXCL_STOP */
     196             :                 }
     197             :         }
     198             : 
     199          20 :         for (i = 0; TEST_HASH64[i].data; ++i) {
     200             :                 uint64_t digest;
     201          19 :                 memcpy(buffer_aligned, TEST_HASH64[i].data, TEST_HASH64[i].len);
     202          19 :                 digest = tommy_hash_u64(TEST_HASH64[i].seed, buffer_aligned, TEST_HASH64[i].len);
     203          19 :                 if (digest != TEST_HASH64[i].digest) {
     204             :                         /* LCOV_EXCL_START */
     205             :                         log_fatal(EINTERNAL, "Failed hash64 test\n");
     206             :                         exit(EXIT_FAILURE);
     207             :                         /* LCOV_EXCL_STOP */
     208             :                 }
     209             :         }
     210             : 
     211             : 
     212         264 :         for (i = 0; TEST_MURMUR3[i].data; ++i) {
     213             :                 unsigned char digest[HASH_MAX];
     214         263 :                 memcpy(buffer_aligned, TEST_MURMUR3[i].data, TEST_MURMUR3[i].len);
     215         263 :                 memcpy(seed_aligned, TEST_MURMUR3[i].seed, HASH_MAX);
     216         263 :                 memhash(HASH_MURMUR3, seed_aligned, digest, buffer_aligned, TEST_MURMUR3[i].len);
     217         263 :                 if (memcmp(digest, TEST_MURMUR3[i].digest, HASH_MAX) != 0) {
     218             :                         /* LCOV_EXCL_START */
     219             :                         log_fatal(EINTERNAL, "Failed Murmur3 test\n");
     220             :                         exit(EXIT_FAILURE);
     221             :                         /* LCOV_EXCL_STOP */
     222             :                 }
     223             :         }
     224             : 
     225         264 :         for (i = 0; TEST_SPOOKY2[i].data; ++i) {
     226             :                 unsigned char digest[HASH_MAX];
     227         263 :                 memcpy(buffer_aligned, TEST_SPOOKY2[i].data, TEST_SPOOKY2[i].len);
     228         263 :                 memcpy(seed_aligned, TEST_SPOOKY2[i].seed, HASH_MAX);
     229         263 :                 memhash(HASH_SPOOKY2, seed_aligned, digest, buffer_aligned, TEST_SPOOKY2[i].len);
     230         263 :                 if (memcmp(digest, TEST_SPOOKY2[i].digest, HASH_MAX) != 0) {
     231             :                         /* LCOV_EXCL_START */
     232             :                         log_fatal(EINTERNAL, "Failed Spooky2 test\n");
     233             :                         exit(EXIT_FAILURE);
     234             :                         /* LCOV_EXCL_STOP */
     235             :                 }
     236             :         }
     237             : 
     238         266 :         for (i = 0; TEST_METRO[i].data; ++i) {
     239             :                 unsigned char digest[HASH_MAX];
     240         265 :                 memcpy(buffer_aligned, TEST_METRO[i].data, TEST_METRO[i].len);
     241         265 :                 memcpy(seed_aligned, TEST_METRO[i].seed, HASH_MAX);
     242         265 :                 memhash(HASH_METRO, seed_aligned, digest, buffer_aligned, TEST_METRO[i].len);
     243         265 :                 if (memcmp(digest, TEST_METRO[i].digest, HASH_MAX) != 0) {
     244             :                         /* LCOV_EXCL_START */
     245             :                         log_fatal(EINTERNAL, "Failed Metro test\n");
     246             :                         exit(EXIT_FAILURE);
     247             :                         /* LCOV_EXCL_STOP */
     248             :                 }
     249             :         }
     250             : 
     251         226 :         for (i = 0; TEST_MUSEAIR[i].data; ++i) {
     252             :                 unsigned char digest[HASH_MAX];
     253         225 :                 memcpy(buffer_aligned, TEST_MUSEAIR[i].data, TEST_MUSEAIR[i].len);
     254         225 :                 memcpy(seed_aligned, TEST_MUSEAIR[i].seed, HASH_MAX);
     255         225 :                 memhash(HASH_MUSEAIR, seed_aligned, digest, buffer_aligned, TEST_MUSEAIR[i].len);
     256         225 :                 if (memcmp(digest, TEST_MUSEAIR[i].digest, HASH_MAX) != 0) {
     257             :                         /* LCOV_EXCL_START */
     258             :                         log_fatal(EINTERNAL, "Failed MuseAir test\n");
     259             :                         exit(EXIT_FAILURE);
     260             :                         /* LCOV_EXCL_STOP */
     261             :                 }
     262             :         }
     263             : 
     264           1 :         free(buffer_alloc);
     265           1 :         free(seed_alloc);
     266           1 : }
     267             : 
     268             : struct crc_test_vector {
     269             :         const char* data;
     270             :         int len;
     271             :         uint32_t digest;
     272             : };
     273             : 
     274             : /**
     275             :  * Test vectors for CRC32C (Castagnoli)
     276             :  */
     277             : static struct crc_test_vector TEST_CRC32C[] = {
     278             :         { "", 0, 0 },
     279             :         { "\x61", 1, 0xc1d04330 },
     280             :         { "\x66\x6f\x6f", 3, 0xcfc4ae1d },
     281             :         { "\x68\x65\x6c\x6c\x6f\x20\x77\x6f\x72\x6c\x64", 11, 0xc99465aa },
     282             :         { "\x68\x65\x6c\x6c\x6f\x20", 6, 0x7e627e58 },
     283             :         { "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 32, 0x8a9136aa },
     284             :         { "\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff", 32, 0x62a8ab43 },
     285             :         { "\x1f\x1e\x1d\x1c\x1b\x1a\x19\x18\x17\x16\x15\x14\x13\x12\x11\x10\x0f\x0e\x0d\x0c\x0b\x0a\x09\x08\x07\x06\x05\x04\x03\x02\x01\x00", 32, 0x113fdb5c },
     286             :         { "\x01\xc0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x14\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\x14\x00\x00\x00\x18\x28\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00", 48, 0xd9963a56 },
     287             :         { "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f", 32, 0x46dd794e },
     288             :         { "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28", 40, 0x0e2c157f },
     289             :         { "\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50", 40, 0xe980ebf6 },
     290             :         { "\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78", 40, 0xde74bded },
     291             :         { "\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0", 40, 0xd579c862 },
     292             :         { "\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8", 40, 0xba979ad0 },
     293             :         { "\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0", 40, 0x2b29d913 },
     294             :         { "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0", 240, 0x24c5d375 },
     295             :         { 0, 0, 0 }
     296             : };
     297             : 
     298           1 : static void test_crc32c(void)
     299             : {
     300             :         unsigned i;
     301             : 
     302          18 :         for (i = 0; TEST_CRC32C[i].data; ++i) {
     303             :                 uint32_t digest;
     304             :                 uint32_t digest_gen;
     305             : 
     306          17 :                 digest = crc32c(0, (const unsigned char*)TEST_CRC32C[i].data, TEST_CRC32C[i].len);
     307          17 :                 digest_gen = crc32c_gen(0, (const unsigned char*)TEST_CRC32C[i].data, TEST_CRC32C[i].len);
     308             : 
     309          17 :                 if (digest != TEST_CRC32C[i].digest || digest_gen != TEST_CRC32C[i].digest) {
     310             :                         /* LCOV_EXCL_START */
     311             :                         log_fatal(EINTERNAL, "Failed CRC32C test\n");
     312             :                         exit(EXIT_FAILURE);
     313             :                         /* LCOV_EXCL_STOP */
     314             :                 }
     315             :         }
     316           1 : }
     317             : 
     318             : /**
     319             :  * Size of tommy data structures.
     320             :  */
     321             : #define TOMMY_SIZE 256
     322             : 
     323         384 : static int tommy_test_search(const void* arg, const void* obj)
     324             : {
     325         384 :         return arg != obj;
     326             : }
     327             : 
     328        4324 : static int tommy_test_compare(const void* void_arg_a, const void* void_arg_b)
     329             : {
     330        4324 :         if (void_arg_a < void_arg_b)
     331        2007 :                 return -1;
     332        2317 :         if (void_arg_a > void_arg_b)
     333        2058 :                 return 1;
     334         259 :         return 0;
     335             : }
     336             : 
     337             : static unsigned tommy_test_foreach_count;
     338             : 
     339         512 : static void tommy_test_foreach(void* obj)
     340             : {
     341             :         (void)obj;
     342             : 
     343         512 :         ++tommy_test_foreach_count;
     344         512 : }
     345             : 
     346         512 : static void tommy_test_foreach_arg(void* void_arg, void* obj)
     347             : {
     348         512 :         unsigned* arg = void_arg;
     349             : 
     350             :         (void)obj;
     351             : 
     352         512 :         ++*arg;
     353         512 : }
     354             : 
     355           1 : static void test_tommy(void)
     356             : {
     357             :         tommy_array array;
     358             :         tommy_arrayblkof arrayblkof;
     359             :         tommy_list list;
     360             :         tommy_hashdyn hashdyn;
     361             :         tommy_tree tree;
     362             :         tommy_node node[TOMMY_SIZE + 1];
     363             :         unsigned i;
     364             : 
     365           1 :         tommy_array_init(&array);
     366           1 :         tommy_arrayblkof_init(&arrayblkof, sizeof(unsigned));
     367             : 
     368         257 :         for (i = 0; i < TOMMY_SIZE; ++i) {
     369         256 :                 tommy_array_insert(&array, &node[i]);
     370         256 :                 tommy_arrayblkof_grow(&arrayblkof, i + 1);
     371         256 :                 *(unsigned*)tommy_arrayblkof_ref(&arrayblkof, i) = i;
     372             :         }
     373             : 
     374           1 :         tommy_array_grow(&array, TOMMY_SIZE);
     375           1 :         tommy_arrayblkof_grow(&arrayblkof, TOMMY_SIZE);
     376             : 
     377           1 :         if (tommy_array_memory_usage(&array) < TOMMY_SIZE * sizeof(void*)) {
     378             :                 /* LCOV_EXCL_START */
     379             :                 goto bail;
     380             :                 /* LCOV_EXCL_STOP */
     381             :         }
     382           1 :         if (tommy_arrayblkof_memory_usage(&arrayblkof) < TOMMY_SIZE * sizeof(unsigned)) {
     383             :                 /* LCOV_EXCL_START */
     384             :                 goto bail;
     385             :                 /* LCOV_EXCL_STOP */
     386             :         }
     387             : 
     388         257 :         for (i = 0; i < TOMMY_SIZE; ++i) {
     389         256 :                 if (tommy_array_get(&array, i) != &node[i]) {
     390             :                         /* LCOV_EXCL_START */
     391             :                         goto bail;
     392             :                         /* LCOV_EXCL_STOP */
     393             :                 }
     394         256 :                 if (*(unsigned*)tommy_arrayblkof_ref(&arrayblkof, i) != i) {
     395             :                         /* LCOV_EXCL_START */
     396             :                         goto bail;
     397             :                         /* LCOV_EXCL_STOP */
     398             :                 }
     399             :         }
     400             : 
     401           1 :         tommy_arrayblkof_done(&arrayblkof);
     402           1 :         tommy_array_done(&array);
     403             : 
     404           1 :         tommy_list_init(&list);
     405             : 
     406           1 :         if (!tommy_list_empty(&list)) {
     407             :                 /* LCOV_EXCL_START */
     408             :                 goto bail;
     409             :                 /* LCOV_EXCL_STOP */
     410             :         }
     411             : 
     412           1 :         if (tommy_list_tail(&list)) {
     413             :                 /* LCOV_EXCL_START */
     414             :                 goto bail;
     415             :                 /* LCOV_EXCL_STOP */
     416             :         }
     417             : 
     418           1 :         if (tommy_list_head(&list)) {
     419             :                 /* LCOV_EXCL_START */
     420             :                 goto bail;
     421             :                 /* LCOV_EXCL_STOP */
     422             :         }
     423             : 
     424           1 :         tommy_list_insert_tail(&list, &node[0], &node[0]);
     425             : 
     426           1 :         if (tommy_list_tail(&list) != tommy_list_head(&list)) {
     427             :                 /* LCOV_EXCL_START */
     428             :                 goto bail;
     429             :                 /* LCOV_EXCL_STOP */
     430             :         }
     431             : 
     432           1 :         tommy_hashdyn_init(&hashdyn);
     433             : 
     434         257 :         for (i = 0; i < TOMMY_SIZE; ++i)
     435         256 :                 tommy_hashdyn_insert(&hashdyn, &node[i], &node[i], i % 64);
     436             : 
     437           1 :         if (tommy_hashdyn_count(&hashdyn) != TOMMY_SIZE) {
     438             :                 /* LCOV_EXCL_START */
     439             :                 goto bail;
     440             :                 /* LCOV_EXCL_STOP */
     441             :         }
     442             : 
     443           1 :         if (tommy_hashdyn_memory_usage(&hashdyn) < TOMMY_SIZE * sizeof(tommy_node)) {
     444             :                 /* LCOV_EXCL_START */
     445             :                 goto bail;
     446             :                 /* LCOV_EXCL_STOP */
     447             :         }
     448             : 
     449           1 :         tommy_test_foreach_count = 0;
     450           1 :         tommy_hashdyn_foreach(&hashdyn, tommy_test_foreach);
     451           1 :         if (tommy_test_foreach_count != TOMMY_SIZE) {
     452             :                 /* LCOV_EXCL_START */
     453             :                 goto bail;
     454             :                 /* LCOV_EXCL_STOP */
     455             :         }
     456             : 
     457           1 :         tommy_test_foreach_count = 0;
     458           1 :         tommy_hashdyn_foreach_arg(&hashdyn, tommy_test_foreach_arg, &tommy_test_foreach_count);
     459           1 :         if (tommy_test_foreach_count != TOMMY_SIZE) {
     460             :                 /* LCOV_EXCL_START */
     461             :                 goto bail;
     462             :                 /* LCOV_EXCL_STOP */
     463             :         }
     464             : 
     465         129 :         for (i = 0; i < TOMMY_SIZE / 2; ++i)
     466         128 :                 tommy_hashdyn_remove_existing(&hashdyn, &node[i]);
     467             : 
     468         129 :         for (i = 0; i < TOMMY_SIZE / 2; ++i) {
     469         128 :                 if (tommy_hashdyn_remove(&hashdyn, tommy_test_search, &node[i], i % 64) != 0) {
     470             :                         /* LCOV_EXCL_START */
     471             :                         goto bail;
     472             :                         /* LCOV_EXCL_STOP */
     473             :                 }
     474             :         }
     475         129 :         for (i = TOMMY_SIZE / 2; i < TOMMY_SIZE; ++i) {
     476         128 :                 if (tommy_hashdyn_remove(&hashdyn, tommy_test_search, &node[i], i % 64) == 0) {
     477             :                         /* LCOV_EXCL_START */
     478             :                         goto bail;
     479             :                         /* LCOV_EXCL_STOP */
     480             :                 }
     481             :         }
     482             : 
     483           1 :         if (tommy_hashdyn_count(&hashdyn) != 0) {
     484             :                 /* LCOV_EXCL_START */
     485             :                 goto bail;
     486             :                 /* LCOV_EXCL_STOP */
     487             :         }
     488             : 
     489           1 :         tommy_hashdyn_done(&hashdyn);
     490             : 
     491           1 :         tommy_tree_init(&tree, tommy_test_compare);
     492             : 
     493         257 :         for (i = 0; i < TOMMY_SIZE; ++i)
     494         256 :                 tommy_tree_insert(&tree, &node[i], (void*)(uintptr_t)(i + 1));
     495             : 
     496             :         /* try to insert a duplicate, count should not change */
     497           1 :         tommy_tree_insert(&tree, &node[TOMMY_SIZE], (void*)(uintptr_t)1);
     498             : 
     499           1 :         if (tommy_tree_count(&tree) != TOMMY_SIZE) {
     500             :                 /* LCOV_EXCL_START */
     501             :                 goto bail;
     502             :                 /* LCOV_EXCL_STOP */
     503             :         }
     504           1 :         if (tommy_tree_memory_usage(&tree) < TOMMY_SIZE * sizeof(tommy_node)) {
     505             :                 /* LCOV_EXCL_START */
     506             :                 goto bail;
     507             :                 /* LCOV_EXCL_STOP */
     508             :         }
     509           1 :         if (tommy_tree_search(&tree, (void*)1) != (void*)1) {
     510             :                 /* LCOV_EXCL_START */
     511             :                 goto bail;
     512             :                 /* LCOV_EXCL_STOP */
     513             :         }
     514           1 :         if (tommy_tree_search(&tree, (void*)-1) != 0) {
     515             :                 /* LCOV_EXCL_START */
     516             :                 goto bail;
     517             :                 /* LCOV_EXCL_STOP */
     518             :         }
     519           1 :         if (tommy_tree_search_compare(&tree, tommy_test_compare, (void*)1) != (void*)1) {
     520             :                 /* LCOV_EXCL_START */
     521             :                 goto bail;
     522             :                 /* LCOV_EXCL_STOP */
     523             :         }
     524           1 :         if (tommy_tree_search_compare(&tree, tommy_test_compare, (void*)-1) != 0) {
     525             :                 /* LCOV_EXCL_START */
     526             :                 goto bail;
     527             :                 /* LCOV_EXCL_STOP */
     528             :         }
     529             : 
     530           1 :         tommy_test_foreach_count = 0;
     531           1 :         tommy_tree_foreach(&tree, tommy_test_foreach);
     532           1 :         if (tommy_test_foreach_count != TOMMY_SIZE) {
     533             :                 /* LCOV_EXCL_START */
     534             :                 goto bail;
     535             :                 /* LCOV_EXCL_STOP */
     536             :         }
     537             : 
     538           1 :         tommy_test_foreach_count = 0;
     539           1 :         tommy_tree_foreach_arg(&tree, tommy_test_foreach_arg, &tommy_test_foreach_count);
     540           1 :         if (tommy_test_foreach_count != TOMMY_SIZE) {
     541             :                 /* LCOV_EXCL_START */
     542             :                 goto bail;
     543             :                 /* LCOV_EXCL_STOP */
     544             :         }
     545             : 
     546         129 :         for (i = 0; i < TOMMY_SIZE / 2; ++i)
     547         128 :                 tommy_tree_remove_existing(&tree, &node[i]);
     548             : 
     549         129 :         for (i = 0; i < TOMMY_SIZE / 2; ++i) {
     550         128 :                 if (tommy_tree_remove(&tree, (void*)(uintptr_t)(i + 1)) != 0) {
     551             :                         /* LCOV_EXCL_START */
     552             :                         goto bail;
     553             :                         /* LCOV_EXCL_STOP */
     554             :                 }
     555             :         }
     556             : 
     557         129 :         for (i = TOMMY_SIZE / 2; i < TOMMY_SIZE; ++i) {
     558         128 :                 if (tommy_tree_remove(&tree, (void*)(uintptr_t)(i + 1)) == 0) {
     559             :                         /* LCOV_EXCL_START */
     560             :                         goto bail;
     561             :                         /* LCOV_EXCL_STOP */
     562             :                 }
     563             :         }
     564             : 
     565           1 :         if (tommy_tree_count(&tree) != 0) {
     566             :                 /* LCOV_EXCL_START */
     567             :                 goto bail;
     568             :                 /* LCOV_EXCL_STOP */
     569             :         }
     570             : 
     571           1 :         return;
     572           0 : bail:
     573             :         /* LCOV_EXCL_START */
     574             :         log_fatal(EINTERNAL, "Failed tommy test\n");
     575             :         exit(EXIT_FAILURE);
     576             :         /* LCOV_EXCL_STOP */
     577             : }
     578             : 
     579             : struct {
     580             :         const char* pattern;
     581             :         const char* text;
     582             :         int result;
     583             : } WNMATCH_TEST[] = {
     584             :         /* basic literal matching */
     585             :         { "hello", "hello", 0 },
     586             :         { "hello", "world", 1 },
     587             :         { "", "", 0 },
     588             :         { "hello", "", 1 },
     589             :         { "", "hello", 1 },
     590             : 
     591             :         /* single asterisk (*) */
     592             :         { "*", "anything", 0 },
     593             :         { "*", "", 0 },
     594             :         { "*.txt", "file.txt", 0 },
     595             :         { "*.txt", "file.doc", 1 },
     596             :         { "*file*", "myfile.txt", 0 },
     597             :         { "f*le", "file", 0 },
     598             :         { "f*le", "fiiiile", 0 },
     599             :         { "f*le", "folder", 1 },
     600             :         { "a*b*c", "abc", 0 },
     601             :         { "a*b*c", "aXbYc", 0 },
     602             :         { "a*b*c", "aXXbYYc", 0 },
     603             :         { "a*b*c", "ac", 1 },
     604             :         { "***", "anything", 0 },
     605             :         { "*.txt", "notes.txt", 0 },
     606             :         { "*.txt", "folder/notes.txt", 1 },
     607             :         { "*.js", "main.jsx", 1 },
     608             : 
     609             :         /* single asterisk with / */
     610             :         { "*", "a/b", 1 },
     611             :         { "*.txt", "dir/file.txt", 1 },
     612             :         { "dir/*.txt", "dir/file.txt", 0 },
     613             :         { "*/*.txt", "dir/file.txt", 0 },
     614             :         { "*/*.txt", "a/b/file.txt", 1 },
     615             : 
     616             :         /* question mark (?) */
     617             :         { "?", "a", 0 },
     618             :         { "?", "ab", 1 },
     619             :         { "?", "", 1 },
     620             :         { "file?.txt", "file1.txt", 0 },
     621             :         { "file?.txt", "fileA.txt", 0 },
     622             :         { "file?.txt", "file10.txt", 1 },
     623             :         { "???", "abc", 0 },
     624             :         { "???", "ab", 1 },
     625             :         { "a?c", "abc", 0 },
     626             :         { "a?c", "ac", 1 },
     627             :         { "file?.txt", "file1.txt", 0 },
     628             :         { "file?.txt", "file12.txt", 1 },
     629             : 
     630             :         /* question mark with / */
     631             :         { "?", "/", 1 },
     632             :         { "dir?file", "dir/file", 1 },
     633             :         { "dir?file", "dirAfile", 0 },
     634             : 
     635             :         /* character classes [...] */
     636             :         { "[abc]", "a", 0 },
     637             :         { "[abc]", "b", 0 },
     638             :         { "[abc]", "c", 0 },
     639             :         { "[abc]", "d", 1 },
     640             :         { "[abc]", "", 1 },
     641             :         { "file[0-9].txt", "file5.txt", 0 },
     642             :         { "file[0-9].txt", "fileA.txt", 1 },
     643             :         { "[a-z]", "m", 0 },
     644             :         { "[A-Z]", "M", 0 },
     645             :         { "[0-9a-f]", "a", 0 },
     646             :         { "[0-9a-f]", "5", 0 },
     647             :         { "[0-9a-f]", "g", 1 },
     648             :         { "[a-z].js", "p.js", 0 },
     649             :         { "[a-z].js", "1.js", 1 },
     650             :         { "[0-9].txt", "a.txt", 1 },
     651             :         { "[!a-z].js", "b.js", 1 },
     652             : 
     653             :         /* negated character classes [!...] */
     654             :         { "[!abc]", "d", 0 },
     655             :         { "[!abc]", "a", 1 },
     656             :         { "[!0-9]", "a", 0 },
     657             :         { "[!0-9]", "5", 1 },
     658             :         { "file[!0-9].txt", "filea.txt", 0 },
     659             :         { "file[!0-9].txt", "file5.txt", 1 },
     660             :         { "[^abc]", "d", 0 },
     661             :         { "[^abc]", "a", 1 },
     662             : 
     663             :         /* character classes with / */
     664             :         { "[a-z]", "/", 1 },
     665             :         { "dir[/]file", "dir/file", 1 },
     666             : 
     667             : #ifdef WIN32
     668             :         /* case */
     669             :         { "hello", "HELLO", 0 },
     670             :         { "Hello", "hello", 0 },
     671             :         { "*.TXT", "file.txt", 0 },
     672             :         { "FILE.txt", "file.TXT", 0 },
     673             :         { "[a-z]", "A", 0 },
     674             :         { "[ABC]", "b", 0 },
     675             :         { "[a-z].js", "A.js", 0 },
     676             :         { "[a-z]", "M", 0 },
     677             : #else
     678             :         { "hello", "HELLO", 1 },
     679             :         { "Hello", "hello", 1 },
     680             :         { "*.TXT", "file.txt", 1 },
     681             :         { "FILE.txt", "file.TXT", 1 },
     682             :         { "[a-z]", "A", 1 },
     683             :         { "[ABC]", "b", 1 },
     684             :         { "[a-z].js", "A.js", 1 },
     685             :         { "[a-z]", "M", 1 },
     686             : #endif
     687             : 
     688             :         /* the /xx/ collapse case */
     689             :         { "a/**/b", "a/b", 0 },
     690             :         { "a/**/b", "a/x/b", 0 },
     691             : 
     692             :         /* double asterisk (xx/) at start */
     693             :         { "**/*.txt", "file.txt", 0 },
     694             :         { "**/*.txt", "dir/file.txt", 0 },
     695             :         { "**/*.txt", "a/b/c/file.txt", 0 },
     696             :         { "**/*.txt", "file.doc", 1 },
     697             :         { "**/test.txt", "test.txt", 0 },
     698             :         { "**/test.txt", "a/b/test.txt", 0 },
     699             :         { "**/test.txt", "a/b/other.txt", 1 },
     700             :         { "**/*file*", "myfile.txt", 0 },
     701             :         { "**/*file*", "dir/myfile.txt", 0 },
     702             : 
     703             :         /* double asterisk (/xx) at end */
     704             :         { "src/**", "src/", 0 },
     705             :         { "src/**", "src/file.c", 0 },
     706             :         { "src/**", "src/a/b/c/file.c", 0 },
     707             :         { "src/**", "other/file.c", 1 },
     708             :         { "src/**", "src", 1 },
     709             :         { "dir/**", "dir/subdir/", 0 },
     710             : 
     711             :         /* double asterisk (/xx/) in middle */
     712             :         { "src/**/*.c", "src/file.c", 0 },
     713             :         { "src/**/*.c", "src/lib/file.c", 0 },
     714             :         { "src/**/*.c", "src/lib/util/file.c", 0 },
     715             :         { "src/**/*.c", "src/file.h", 1 },
     716             :         { "src/**/*.c", "other/file.c", 1 },
     717             :         { "a/**/b/**/c", "a/b/c", 0 },
     718             :         { "a/**/b/**/c", "a/x/b/y/c", 0 },
     719             :         { "a/**/b/**/c", "a/x/y/b/z/w/c", 0 },
     720             :         { "a/**/b", "a/x/y/z/b", 0 },
     721             :         { "/docs/**/api.md", "/docs/api.md", 0 },
     722             :         { "a/**/b", "a/xb", 1 },
     723             :         { "a/**/b", "ax/b", 1 },
     724             :         { "a/**/b", "a/c/xb", 1 },
     725             :         { "a/**/b", "ax/c/b", 1 },
     726             :         { "a/**/b", "a/x/y/c", 1 },
     727             :         { "a/**/b", "axb", 1 },
     728             : 
     729             :         /* multiple recursion segments */
     730             :         { "**/**/file", "file", 0 },
     731             :         { "**/**/file", "a/b/c/file", 0 },
     732             :         { "a/**/b/**/c", "a/b/c", 0 },
     733             :         { "a/**/b/**/c", "a/1/b/2/c", 0 },
     734             : 
     735             :         /* combined patterns */
     736             :         { "*.{txt,doc}", "file.txt", 1 },
     737             :         { "file[0-9]*.txt", "file5abc.txt", 0 },
     738             :         { "dir/*/file?.txt", "dir/sub/file1.txt", 0 },
     739             :         { "**/src/**/*.c", "project/src/lib/file.c", 0 },
     740             : 
     741             :         /* edge cases */
     742             :         { "**", "anything", 0 },
     743             :         { "a/**", "a/b", 0 },
     744             :         { "a**", "aaa", 0 },
     745             :         { "**a", "xxa", 0 },
     746             :         { "a/**/", "a/b/", 0 },
     747             :         { "a/**/b", "a/b", 0 },
     748             :         { "a/**/b", "a//b", 0 },
     749             :         { "*/**/file.txt", "a/file.txt", 0 },
     750             :         { "*/**/file.txt", "a/b/c/file.txt", 0 },
     751             :         { "a**/file.txt", "afile.txt", 1 },
     752             :         { "/*/**/file.txt", "/file.txt", 1 },
     753             :         { "*/**/file.txt", "/file.txt", 0 },
     754             :         { "src/**/**/file.txt", "src/file.txt", 0 },
     755             :         { "src/**/**/file.txt", "src/sub/file.txt", 0 },
     756             :         { "src/***/file.txt", "src/file.txt", 0 },
     757             :         { "src/***/file.txt", "src/sub/file.txt", 0 },
     758             :         { "src/***/file.txt", "src/sub/sub/file.txt", 0 },
     759             :         { "src/****/file.txt", "src/file.txt", 0 },
     760             :         { "src/****/file.txt", "src/sub/file.txt", 0 },
     761             :         { "src/****/file.txt", "src/sub/sub/file.txt", 0 },
     762             :         { "**/build", "a/b/build", 0 },
     763             :         { "src/**/test.js", "src/ui/test.js", 0 },
     764             :         { "dist/**", "dist/bin/app.exe", 0 },
     765             :         { "src-**", "src-folder/file.js", 1 },
     766             :         { "**pkg/init.py", "libs/core/pkg/init.py", 1 },
     767             :         { "**.log", "error.log", 0 },
     768             :         { "**.log", "var/log/sys.log", 1 },
     769             :         { "src/**.js", "src/app.js", 0 },
     770             :         { "src/**.js", "src/components/ui/button.js", 0 }, /* <<<<< .GITIGNORE DIFFERS */
     771             :         { "a**b.txt", "ab.txt", 0 },
     772             :         { "a**b.txt", "axxb.txt", 0 },
     773             :         { "a**b.txt", "a/b.txt", 1 },
     774             :         { "a**b.txt", "a/subdir/b.txt", 1 },
     775             :         { "a**b.txt", "a_folder/sub/b.txt", 1 },
     776             :         { "a**b.txt", "a_folder/sub/folter_b.txt", 1 },
     777             :         { "**/build", "build", 0 },
     778             :         { "**/build", "project/out/build", 0 },
     779             : 
     780             :         /* negative tests */
     781             :         { "/docs/**/api.md", "docs/api.txt", 1 },
     782             :         { "a/**/b", "a/b/c", 1 },
     783             :         { "static/**", "static", 1 },
     784             :         { "src/*.js", "src/ui/app.js", 1 },
     785             :         { "/config.*", "etc/config.json", 1 },
     786             :         { "*/*/*.c", "main.c", 1 },
     787             :         { "a/*/b", "a/b", 1 },
     788             :         { "a/**/b", "axb", 1 },
     789             :         { "a/**/b", "ab", 1 },
     790             :         { "/**/logs", "logs", 1 },
     791             :         { "/src/**/logs", "src/web/log", 1 },
     792             :         { "foo//bar", "foo/bar", 1 },
     793             :         { "a/**/b", "a/b/", 1 },
     794             :         { "a**b**c", "acb", 1 },
     795             :         { "src-**-pkg", "src-pkg", 1 },
     796             :         { "**/test/*.js", "test/ui/app.js", 1 },
     797             : 
     798             :         /* complex real-world patterns */
     799             :         { "**/.git/**", ".git/config", 0 },
     800             :         { "**/.git/**", "project/.git/hooks/pre-commit", 0 },
     801             :         { "**/node_modules/**", "node_modules/pkg/index.js", 0 },
     802             :         { "**/node_modules/**", "app/node_modules/pkg/file.js", 0 },
     803             :         { "src/**/*.{c,h}", "src/main.c", 1 },
     804             :         { "**/test_*.py", "test_example.py", 0 },
     805             :         { "**/test_*.py", "tests/test_feature.py", 0 },
     806             : 
     807             :         /* performance/stress patterns */
     808             :         { "a*b*c*d*e*f*g*h*i*j*k", "abcdefghijk", 0 },
     809             :         { "a*b*c*d*e*f*g*h*i*j*k", "aXbXcXdXeXfXgXhXiXjXk", 0 },
     810             :         { "**/**/**/*.txt", "a/b/c/d/e/f.txt", 0 },
     811             : 
     812             :         /* trailing/leading slashes */
     813             :         { "dir/", "dir/", 0 },
     814             :         { "/root/*", "/root/file", 0 },
     815             : 
     816             :         /* complex embedded patterns */
     817             :         { "src-**-pkg/*.js", "src-web-pkg/main.js", 0 },
     818             :         { "src-**-pkg/*.js", "src-lazy-load-ui-pkg/main.js", 0 },
     819             :         { "src-**-pkg/*.js", "src-web-pkg/subdir/main.js", 1 },
     820             : 
     821             :         /* anchoring and slashes */
     822             :         { "/root.txt", "root.txt", 1 },
     823             :         { "/root.txt", "subdir/root.txt", 1 },
     824             :         { "docs/", "docs", 1 },
     825             :         { "docs/", "docs/", 0 },
     826             :         { "**/temp/", "src/temp/", 0 },
     827             :         { "**/temp/", "src/temp", 1 },
     828             : 
     829             :         { 0 }
     830             : };
     831             : 
     832           1 : static void test_wnmatch(void)
     833             : {
     834         191 :         for (int i = 0; WNMATCH_TEST[i].pattern; ++i) {
     835         190 :                 if (wnmatch(WNMATCH_TEST[i].pattern, WNMATCH_TEST[i].text) != WNMATCH_TEST[i].result) {
     836             :                         /* LCOV_EXCL_START */
     837             :                         log_fatal(EINTERNAL, "Failed wnmatch test %s %s, expected %d\n", WNMATCH_TEST[i].pattern, WNMATCH_TEST[i].text, WNMATCH_TEST[i].result);
     838             :                         exit(EXIT_FAILURE);
     839             :                         /* LCOV_EXCL_STOP */
     840             :                 }
     841             :         }
     842           1 : }
     843             : 
     844           1 : void selftest(void)
     845             : {
     846           1 :         log_tag("selftest:\n");
     847           1 :         log_flush();
     848             : 
     849           1 :         msg_progress("Self-test...\n");
     850             : 
     851             :         /* large file check */
     852             :         if (sizeof(off_t) < sizeof(uint64_t)) {
     853             :                 /* LCOV_EXCL_START */
     854             :                 log_fatal(EINTERNAL, "Missing support for large files\n");
     855             :                 exit(EXIT_FAILURE);
     856             :                 /* LCOV_EXCL_STOP */
     857             :         }
     858             : 
     859           1 :         if (util_selftest() != 0) {
     860             :                 /* LCOV_EXCL_START */
     861             :                 log_fatal(EINTERNAL, "Failed UTIL test\n");
     862             :                 exit(EXIT_FAILURE);
     863             :                 /* LCOV_EXCL_STOP */
     864             :         }
     865           1 :         test_hash();
     866           1 :         test_crc32c();
     867           1 :         test_tommy();
     868           1 :         test_wnmatch();
     869           1 :         if (raid_selftest() != 0) {
     870             :                 /* LCOV_EXCL_START */
     871             :                 log_fatal(EINTERNAL, "Failed SELF test\n");
     872             :                 exit(EXIT_FAILURE);
     873             :                 /* LCOV_EXCL_STOP */
     874             :         }
     875           1 :         if (raid_test_sort() != 0) {
     876             :                 /* LCOV_EXCL_START */
     877             :                 log_fatal(EINTERNAL, "Failed SORT test\n");
     878             :                 exit(EXIT_FAILURE);
     879             :                 /* LCOV_EXCL_STOP */
     880             :         }
     881           1 :         if (raid_test_insert() != 0) {
     882             :                 /* LCOV_EXCL_START */
     883             :                 log_fatal(EINTERNAL, "Failed INSERT test\n");
     884             :                 exit(EXIT_FAILURE);
     885             :                 /* LCOV_EXCL_STOP */
     886             :         }
     887           1 :         if (raid_test_combo() != 0) {
     888             :                 /* LCOV_EXCL_START */
     889             :                 log_fatal(EINTERNAL, "Failed COMBO test\n");
     890             :                 exit(EXIT_FAILURE);
     891             :                 /* LCOV_EXCL_STOP */
     892             :         }
     893           1 :         if (raid_test_par(RAID_MODE_VANDERMONDE, 32, 256) != 0) {
     894             :                 /* LCOV_EXCL_START */
     895             :                 log_fatal(EINTERNAL, "Failed GEN Vandermonde test\n");
     896             :                 exit(EXIT_FAILURE);
     897             :                 /* LCOV_EXCL_STOP */
     898             :         }
     899           1 :         if (raid_test_rec(RAID_MODE_VANDERMONDE, 12, 256) != 0) {
     900             :                 /* LCOV_EXCL_START */
     901             :                 log_fatal(EINTERNAL, "Failed REC Vandermonde test\n");
     902             :                 exit(EXIT_FAILURE);
     903             :                 /* LCOV_EXCL_STOP */
     904             :         }
     905           1 :         if (raid_test_par(RAID_MODE_CAUCHY, 32, 256) != 0) {
     906             :                 /* LCOV_EXCL_START */
     907             :                 log_fatal(EINTERNAL, "Failed GEN Cauchy test\n");
     908             :                 exit(EXIT_FAILURE);
     909             :                 /* LCOV_EXCL_STOP */
     910             :         }
     911           1 :         if (raid_test_rec(RAID_MODE_CAUCHY, 12, 256) != 0) {
     912             :                 /* LCOV_EXCL_START */
     913             :                 log_fatal(EINTERNAL, "Failed REC Cauchy test\n");
     914             :                 exit(EXIT_FAILURE);
     915             :                 /* LCOV_EXCL_STOP */
     916             :         }
     917           1 :         if (raid_test_par(RAID_MODE_CAUCHY, 1, 256) != 0) {
     918             :                 /* LCOV_EXCL_START */
     919             :                 log_fatal(EINTERNAL, "Failed GEN Cauchy test single data disk\n");
     920             :                 exit(EXIT_FAILURE);
     921             :                 /* LCOV_EXCL_STOP */
     922             :         }
     923           1 : }
     924             : 

Generated by: LCOV version 1.0