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
test_crc32c(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
test_crc32c_nvme(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
main(int argc,char ** argv)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