xref: /spdk/test/unit/lib/util/crc32c.c/crc32c_ut.c (revision 8afdeef3becfe9409cc9e7372bd0bc10e8b7d46d)
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