1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright (C) 2017 Intel Corporation. 3 * All rights reserved. 4 */ 5 6 #include "spdk/stdinc.h" 7 8 #include "spdk_internal/cunit.h" 9 10 #include "util/crc32.c" 11 #include "util/crc32c.c" 12 13 static void 14 test_crc32c(void) 15 { 16 uint32_t crc; 17 char buf[1024], buf1[1024]; 18 struct iovec iov[2] = {}; 19 20 /* Verify a string's CRC32-C value against the known correct result. */ 21 snprintf(buf, sizeof(buf), "%s", "Hello world!"); 22 crc = 0xFFFFFFFFu; 23 crc = spdk_crc32c_update(buf, strlen(buf), crc); 24 crc ^= 0xFFFFFFFFu; 25 CU_ASSERT(crc == 0x7b98e751); 26 27 crc = 0xFFFFFFFFu; 28 iov[0].iov_base = buf; 29 iov[0].iov_len = strlen(buf); 30 crc = spdk_crc32c_iov_update(iov, 1, crc); 31 crc ^= 0xFFFFFFFFu; 32 CU_ASSERT(crc == 0x7b98e751); 33 34 crc = 0xFFFFFFFFu; 35 snprintf(buf, sizeof(buf), "%s", "Hello"); 36 iov[0].iov_base = buf; 37 iov[0].iov_len = strlen(buf); 38 39 snprintf(buf1, sizeof(buf1), "%s", " world!"); 40 iov[1].iov_base = buf1; 41 iov[1].iov_len = strlen(buf1); 42 43 crc = spdk_crc32c_iov_update(iov, 2, crc); 44 crc ^= 0xFFFFFFFFu; 45 CU_ASSERT(crc == 0x7b98e751); 46 47 /* 48 * The main loop of the optimized CRC32-C implementation processes data in 8-byte blocks, 49 * followed by a loop to handle the 0-7 trailing bytes. 50 * Test all buffer sizes from 0 to 7 in order to hit all possible trailing byte counts. 51 */ 52 53 /* 0-byte buffer should not modify CRC at all, so final result should be ~0 ^ ~0 == 0 */ 54 snprintf(buf, sizeof(buf), "%s", ""); 55 crc = 0xFFFFFFFFu; 56 crc = spdk_crc32c_update(buf, strlen(buf), crc); 57 crc ^= 0xFFFFFFFFu; 58 CU_ASSERT(crc == 0); 59 60 /* 1-byte buffer */ 61 snprintf(buf, sizeof(buf), "%s", "1"); 62 crc = 0xFFFFFFFFu; 63 crc = spdk_crc32c_update(buf, strlen(buf), crc); 64 crc ^= 0xFFFFFFFFu; 65 CU_ASSERT(crc == 0x90F599E3); 66 67 /* 2-byte buffer */ 68 snprintf(buf, sizeof(buf), "%s", "12"); 69 crc = 0xFFFFFFFFu; 70 crc = spdk_crc32c_update(buf, strlen(buf), crc); 71 crc ^= 0xFFFFFFFFu; 72 CU_ASSERT(crc == 0x7355C460); 73 74 /* 3-byte buffer */ 75 snprintf(buf, sizeof(buf), "%s", "123"); 76 crc = 0xFFFFFFFFu; 77 crc = spdk_crc32c_update(buf, strlen(buf), crc); 78 crc ^= 0xFFFFFFFFu; 79 CU_ASSERT(crc == 0x107B2FB2); 80 81 /* 4-byte buffer */ 82 snprintf(buf, sizeof(buf), "%s", "1234"); 83 crc = 0xFFFFFFFFu; 84 crc = spdk_crc32c_update(buf, strlen(buf), crc); 85 crc ^= 0xFFFFFFFFu; 86 CU_ASSERT(crc == 0xF63AF4EE); 87 88 /* 5-byte buffer */ 89 snprintf(buf, sizeof(buf), "%s", "12345"); 90 crc = 0xFFFFFFFFu; 91 crc = spdk_crc32c_update(buf, strlen(buf), crc); 92 crc ^= 0xFFFFFFFFu; 93 CU_ASSERT(crc == 0x18D12335); 94 95 /* 6-byte buffer */ 96 snprintf(buf, sizeof(buf), "%s", "123456"); 97 crc = 0xFFFFFFFFu; 98 crc = spdk_crc32c_update(buf, strlen(buf), crc); 99 crc ^= 0xFFFFFFFFu; 100 CU_ASSERT(crc == 0x41357186); 101 102 /* 7-byte buffer */ 103 snprintf(buf, sizeof(buf), "%s", "1234567"); 104 crc = 0xFFFFFFFFu; 105 crc = spdk_crc32c_update(buf, strlen(buf), crc); 106 crc ^= 0xFFFFFFFFu; 107 CU_ASSERT(crc == 0x124297EA); 108 109 /* Test a buffer of exactly 8 bytes (one block in the main CRC32-C loop). */ 110 snprintf(buf, sizeof(buf), "%s", "12345678"); 111 crc = 0xFFFFFFFFu; 112 crc = spdk_crc32c_update(buf, strlen(buf), crc); 113 crc ^= 0xFFFFFFFFu; 114 CU_ASSERT(crc == 0x6087809A); 115 } 116 117 static void 118 test_crc32c_nvme(void) 119 { 120 unsigned int buf_size = 4096; 121 char buf[buf_size]; 122 uint32_t crc; 123 unsigned int i, j; 124 125 /* All the expected CRC values are compliant with 126 * the NVM Command Set Specification 1.0c */ 127 128 /* Input buffer = 0s */ 129 memset(buf, 0, buf_size); 130 crc = spdk_crc32c_nvme(buf, buf_size, 0); 131 CU_ASSERT(crc == 0x98F94189); 132 133 /* Input buffer = 1s */ 134 memset(buf, 0xFF, buf_size); 135 crc = spdk_crc32c_nvme(buf, buf_size, 0); 136 CU_ASSERT(crc == 0x25C1FE13); 137 138 /* Input buffer = 0x00, 0x01, 0x02, ... */ 139 memset(buf, 0, buf_size); 140 j = 0; 141 for (i = 0; i < buf_size; i++) { 142 buf[i] = (char)j; 143 if (j == 0xFF) { 144 j = 0; 145 } else { 146 j++; 147 } 148 } 149 crc = spdk_crc32c_nvme(buf, buf_size, 0); 150 CU_ASSERT(crc == 0x9C71FE32); 151 152 /* Input buffer = 0xFF, 0xFE, 0xFD, ... */ 153 memset(buf, 0, buf_size); 154 j = 0xFF; 155 for (i = 0; i < buf_size ; i++) { 156 buf[i] = (char)j; 157 if (j == 0) { 158 j = 0xFF; 159 } else { 160 j--; 161 } 162 } 163 crc = spdk_crc32c_nvme(buf, buf_size, 0); 164 CU_ASSERT(crc == 0x214941A8); 165 } 166 167 int 168 main(int argc, char **argv) 169 { 170 CU_pSuite suite = NULL; 171 unsigned int num_failures; 172 173 CU_initialize_registry(); 174 175 suite = CU_add_suite("crc32c", NULL, NULL); 176 177 CU_ADD_TEST(suite, test_crc32c); 178 CU_ADD_TEST(suite, test_crc32c_nvme); 179 180 181 num_failures = spdk_ut_run_tests(argc, argv, NULL); 182 183 CU_cleanup_registry(); 184 185 return num_failures; 186 } 187