1*9356374aSAndroid Build Coastguard Worker // Copyright 2022 The Abseil Authors
2*9356374aSAndroid Build Coastguard Worker //
3*9356374aSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*9356374aSAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*9356374aSAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*9356374aSAndroid Build Coastguard Worker //
7*9356374aSAndroid Build Coastguard Worker // https://www.apache.org/licenses/LICENSE-2.0
8*9356374aSAndroid Build Coastguard Worker //
9*9356374aSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*9356374aSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*9356374aSAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*9356374aSAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*9356374aSAndroid Build Coastguard Worker // limitations under the License.
14*9356374aSAndroid Build Coastguard Worker
15*9356374aSAndroid Build Coastguard Worker #include "absl/crc/crc32c.h"
16*9356374aSAndroid Build Coastguard Worker
17*9356374aSAndroid Build Coastguard Worker #include <algorithm>
18*9356374aSAndroid Build Coastguard Worker #include <cstddef>
19*9356374aSAndroid Build Coastguard Worker #include <cstdint>
20*9356374aSAndroid Build Coastguard Worker #include <cstring>
21*9356374aSAndroid Build Coastguard Worker #include <sstream>
22*9356374aSAndroid Build Coastguard Worker #include <string>
23*9356374aSAndroid Build Coastguard Worker
24*9356374aSAndroid Build Coastguard Worker #include "gtest/gtest.h"
25*9356374aSAndroid Build Coastguard Worker #include "absl/crc/internal/crc32c.h"
26*9356374aSAndroid Build Coastguard Worker #include "absl/strings/str_cat.h"
27*9356374aSAndroid Build Coastguard Worker #include "absl/strings/str_format.h"
28*9356374aSAndroid Build Coastguard Worker #include "absl/strings/string_view.h"
29*9356374aSAndroid Build Coastguard Worker
30*9356374aSAndroid Build Coastguard Worker namespace {
31*9356374aSAndroid Build Coastguard Worker
TEST(CRC32C,RFC3720)32*9356374aSAndroid Build Coastguard Worker TEST(CRC32C, RFC3720) {
33*9356374aSAndroid Build Coastguard Worker // Test the results of the vectors from
34*9356374aSAndroid Build Coastguard Worker // https://www.rfc-editor.org/rfc/rfc3720#appendix-B.4
35*9356374aSAndroid Build Coastguard Worker char data[32];
36*9356374aSAndroid Build Coastguard Worker
37*9356374aSAndroid Build Coastguard Worker // 32 bytes of ones.
38*9356374aSAndroid Build Coastguard Worker memset(data, 0, sizeof(data));
39*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(absl::ComputeCrc32c(absl::string_view(data, sizeof(data))),
40*9356374aSAndroid Build Coastguard Worker absl::crc32c_t{0x8a9136aa});
41*9356374aSAndroid Build Coastguard Worker
42*9356374aSAndroid Build Coastguard Worker // 32 bytes of ones.
43*9356374aSAndroid Build Coastguard Worker memset(data, 0xff, sizeof(data));
44*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(absl::ComputeCrc32c(absl::string_view(data, sizeof(data))),
45*9356374aSAndroid Build Coastguard Worker absl::crc32c_t{0x62a8ab43});
46*9356374aSAndroid Build Coastguard Worker
47*9356374aSAndroid Build Coastguard Worker // 32 incrementing bytes.
48*9356374aSAndroid Build Coastguard Worker for (int i = 0; i < 32; ++i) data[i] = static_cast<char>(i);
49*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(absl::ComputeCrc32c(absl::string_view(data, sizeof(data))),
50*9356374aSAndroid Build Coastguard Worker absl::crc32c_t{0x46dd794e});
51*9356374aSAndroid Build Coastguard Worker
52*9356374aSAndroid Build Coastguard Worker // 32 decrementing bytes.
53*9356374aSAndroid Build Coastguard Worker for (int i = 0; i < 32; ++i) data[i] = static_cast<char>(31 - i);
54*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(absl::ComputeCrc32c(absl::string_view(data, sizeof(data))),
55*9356374aSAndroid Build Coastguard Worker absl::crc32c_t{0x113fdb5c});
56*9356374aSAndroid Build Coastguard Worker
57*9356374aSAndroid Build Coastguard Worker // An iSCSI - SCSI Read (10) Command PDU.
58*9356374aSAndroid Build Coastguard Worker constexpr uint8_t cmd[48] = {
59*9356374aSAndroid Build Coastguard Worker 0x01, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
60*9356374aSAndroid Build Coastguard Worker 0x00, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00,
61*9356374aSAndroid Build Coastguard Worker 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x18, 0x28, 0x00, 0x00, 0x00,
62*9356374aSAndroid Build Coastguard Worker 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
63*9356374aSAndroid Build Coastguard Worker };
64*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(absl::ComputeCrc32c(absl::string_view(
65*9356374aSAndroid Build Coastguard Worker reinterpret_cast<const char*>(cmd), sizeof(cmd))),
66*9356374aSAndroid Build Coastguard Worker absl::crc32c_t{0xd9963a56});
67*9356374aSAndroid Build Coastguard Worker }
68*9356374aSAndroid Build Coastguard Worker
TestString(size_t len)69*9356374aSAndroid Build Coastguard Worker std::string TestString(size_t len) {
70*9356374aSAndroid Build Coastguard Worker std::string result;
71*9356374aSAndroid Build Coastguard Worker result.reserve(len);
72*9356374aSAndroid Build Coastguard Worker for (size_t i = 0; i < len; ++i) {
73*9356374aSAndroid Build Coastguard Worker result.push_back(static_cast<char>(i % 256));
74*9356374aSAndroid Build Coastguard Worker }
75*9356374aSAndroid Build Coastguard Worker return result;
76*9356374aSAndroid Build Coastguard Worker }
77*9356374aSAndroid Build Coastguard Worker
TEST(CRC32C,Compute)78*9356374aSAndroid Build Coastguard Worker TEST(CRC32C, Compute) {
79*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(absl::ComputeCrc32c(""), absl::crc32c_t{0});
80*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(absl::ComputeCrc32c("hello world"), absl::crc32c_t{0xc99465aa});
81*9356374aSAndroid Build Coastguard Worker }
82*9356374aSAndroid Build Coastguard Worker
TEST(CRC32C,Extend)83*9356374aSAndroid Build Coastguard Worker TEST(CRC32C, Extend) {
84*9356374aSAndroid Build Coastguard Worker uint32_t base = 0xC99465AA; // CRC32C of "Hello World"
85*9356374aSAndroid Build Coastguard Worker std::string extension = "Extension String";
86*9356374aSAndroid Build Coastguard Worker
87*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(
88*9356374aSAndroid Build Coastguard Worker absl::ExtendCrc32c(absl::crc32c_t{base}, extension),
89*9356374aSAndroid Build Coastguard Worker absl::crc32c_t{0xD2F65090}); // CRC32C of "Hello WorldExtension String"
90*9356374aSAndroid Build Coastguard Worker }
91*9356374aSAndroid Build Coastguard Worker
TEST(CRC32C,ExtendByZeroes)92*9356374aSAndroid Build Coastguard Worker TEST(CRC32C, ExtendByZeroes) {
93*9356374aSAndroid Build Coastguard Worker std::string base = "hello world";
94*9356374aSAndroid Build Coastguard Worker absl::crc32c_t base_crc = absl::crc32c_t{0xc99465aa};
95*9356374aSAndroid Build Coastguard Worker
96*9356374aSAndroid Build Coastguard Worker constexpr size_t kExtendByValues[] = {100, 10000, 100000};
97*9356374aSAndroid Build Coastguard Worker for (const size_t extend_by : kExtendByValues) {
98*9356374aSAndroid Build Coastguard Worker SCOPED_TRACE(extend_by);
99*9356374aSAndroid Build Coastguard Worker absl::crc32c_t crc2 = absl::ExtendCrc32cByZeroes(base_crc, extend_by);
100*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(crc2, absl::ComputeCrc32c(base + std::string(extend_by, '\0')));
101*9356374aSAndroid Build Coastguard Worker }
102*9356374aSAndroid Build Coastguard Worker }
103*9356374aSAndroid Build Coastguard Worker
TEST(CRC32C,UnextendByZeroes)104*9356374aSAndroid Build Coastguard Worker TEST(CRC32C, UnextendByZeroes) {
105*9356374aSAndroid Build Coastguard Worker constexpr size_t kExtendByValues[] = {2, 200, 20000, 200000, 20000000};
106*9356374aSAndroid Build Coastguard Worker constexpr size_t kUnextendByValues[] = {0, 100, 10000, 100000, 10000000};
107*9356374aSAndroid Build Coastguard Worker
108*9356374aSAndroid Build Coastguard Worker for (auto seed_crc : {absl::crc32c_t{0}, absl::crc32c_t{0xc99465aa}}) {
109*9356374aSAndroid Build Coastguard Worker SCOPED_TRACE(seed_crc);
110*9356374aSAndroid Build Coastguard Worker for (const size_t size_1 : kExtendByValues) {
111*9356374aSAndroid Build Coastguard Worker for (const size_t size_2 : kUnextendByValues) {
112*9356374aSAndroid Build Coastguard Worker size_t extend_size = std::max(size_1, size_2);
113*9356374aSAndroid Build Coastguard Worker size_t unextend_size = std::min(size_1, size_2);
114*9356374aSAndroid Build Coastguard Worker SCOPED_TRACE(extend_size);
115*9356374aSAndroid Build Coastguard Worker SCOPED_TRACE(unextend_size);
116*9356374aSAndroid Build Coastguard Worker
117*9356374aSAndroid Build Coastguard Worker // Extending by A zeroes an unextending by B<A zeros should be identical
118*9356374aSAndroid Build Coastguard Worker // to extending by A-B zeroes.
119*9356374aSAndroid Build Coastguard Worker absl::crc32c_t crc1 = seed_crc;
120*9356374aSAndroid Build Coastguard Worker crc1 = absl::ExtendCrc32cByZeroes(crc1, extend_size);
121*9356374aSAndroid Build Coastguard Worker crc1 = absl::crc_internal::UnextendCrc32cByZeroes(crc1, unextend_size);
122*9356374aSAndroid Build Coastguard Worker
123*9356374aSAndroid Build Coastguard Worker absl::crc32c_t crc2 = seed_crc;
124*9356374aSAndroid Build Coastguard Worker crc2 = absl::ExtendCrc32cByZeroes(crc2, extend_size - unextend_size);
125*9356374aSAndroid Build Coastguard Worker
126*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(crc1, crc2);
127*9356374aSAndroid Build Coastguard Worker }
128*9356374aSAndroid Build Coastguard Worker }
129*9356374aSAndroid Build Coastguard Worker }
130*9356374aSAndroid Build Coastguard Worker
131*9356374aSAndroid Build Coastguard Worker constexpr size_t kSizes[] = {0, 1, 100, 10000};
132*9356374aSAndroid Build Coastguard Worker for (const size_t size : kSizes) {
133*9356374aSAndroid Build Coastguard Worker SCOPED_TRACE(size);
134*9356374aSAndroid Build Coastguard Worker std::string string_before = TestString(size);
135*9356374aSAndroid Build Coastguard Worker std::string string_after = string_before + std::string(size, '\0');
136*9356374aSAndroid Build Coastguard Worker
137*9356374aSAndroid Build Coastguard Worker absl::crc32c_t crc_before = absl::ComputeCrc32c(string_before);
138*9356374aSAndroid Build Coastguard Worker absl::crc32c_t crc_after = absl::ComputeCrc32c(string_after);
139*9356374aSAndroid Build Coastguard Worker
140*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(crc_before,
141*9356374aSAndroid Build Coastguard Worker absl::crc_internal::UnextendCrc32cByZeroes(crc_after, size));
142*9356374aSAndroid Build Coastguard Worker }
143*9356374aSAndroid Build Coastguard Worker }
144*9356374aSAndroid Build Coastguard Worker
TEST(CRC32C,Concat)145*9356374aSAndroid Build Coastguard Worker TEST(CRC32C, Concat) {
146*9356374aSAndroid Build Coastguard Worker std::string hello = "Hello, ";
147*9356374aSAndroid Build Coastguard Worker std::string world = "world!";
148*9356374aSAndroid Build Coastguard Worker std::string hello_world = absl::StrCat(hello, world);
149*9356374aSAndroid Build Coastguard Worker
150*9356374aSAndroid Build Coastguard Worker absl::crc32c_t crc_a = absl::ComputeCrc32c(hello);
151*9356374aSAndroid Build Coastguard Worker absl::crc32c_t crc_b = absl::ComputeCrc32c(world);
152*9356374aSAndroid Build Coastguard Worker absl::crc32c_t crc_ab = absl::ComputeCrc32c(hello_world);
153*9356374aSAndroid Build Coastguard Worker
154*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(absl::ConcatCrc32c(crc_a, crc_b, world.size()), crc_ab);
155*9356374aSAndroid Build Coastguard Worker }
156*9356374aSAndroid Build Coastguard Worker
TEST(CRC32C,Memcpy)157*9356374aSAndroid Build Coastguard Worker TEST(CRC32C, Memcpy) {
158*9356374aSAndroid Build Coastguard Worker constexpr size_t kBytesSize[] = {0, 1, 20, 500, 100000};
159*9356374aSAndroid Build Coastguard Worker for (size_t bytes : kBytesSize) {
160*9356374aSAndroid Build Coastguard Worker SCOPED_TRACE(bytes);
161*9356374aSAndroid Build Coastguard Worker std::string sample_string = TestString(bytes);
162*9356374aSAndroid Build Coastguard Worker std::string target_buffer = std::string(bytes, '\0');
163*9356374aSAndroid Build Coastguard Worker
164*9356374aSAndroid Build Coastguard Worker absl::crc32c_t memcpy_crc =
165*9356374aSAndroid Build Coastguard Worker absl::MemcpyCrc32c(&(target_buffer[0]), sample_string.data(), bytes);
166*9356374aSAndroid Build Coastguard Worker absl::crc32c_t compute_crc = absl::ComputeCrc32c(sample_string);
167*9356374aSAndroid Build Coastguard Worker
168*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(memcpy_crc, compute_crc);
169*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(sample_string, target_buffer);
170*9356374aSAndroid Build Coastguard Worker }
171*9356374aSAndroid Build Coastguard Worker }
172*9356374aSAndroid Build Coastguard Worker
TEST(CRC32C,RemovePrefix)173*9356374aSAndroid Build Coastguard Worker TEST(CRC32C, RemovePrefix) {
174*9356374aSAndroid Build Coastguard Worker std::string hello = "Hello, ";
175*9356374aSAndroid Build Coastguard Worker std::string world = "world!";
176*9356374aSAndroid Build Coastguard Worker std::string hello_world = absl::StrCat(hello, world);
177*9356374aSAndroid Build Coastguard Worker
178*9356374aSAndroid Build Coastguard Worker absl::crc32c_t crc_a = absl::ComputeCrc32c(hello);
179*9356374aSAndroid Build Coastguard Worker absl::crc32c_t crc_b = absl::ComputeCrc32c(world);
180*9356374aSAndroid Build Coastguard Worker absl::crc32c_t crc_ab = absl::ComputeCrc32c(hello_world);
181*9356374aSAndroid Build Coastguard Worker
182*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(absl::RemoveCrc32cPrefix(crc_a, crc_ab, world.size()), crc_b);
183*9356374aSAndroid Build Coastguard Worker }
184*9356374aSAndroid Build Coastguard Worker
TEST(CRC32C,RemoveSuffix)185*9356374aSAndroid Build Coastguard Worker TEST(CRC32C, RemoveSuffix) {
186*9356374aSAndroid Build Coastguard Worker std::string hello = "Hello, ";
187*9356374aSAndroid Build Coastguard Worker std::string world = "world!";
188*9356374aSAndroid Build Coastguard Worker std::string hello_world = absl::StrCat(hello, world);
189*9356374aSAndroid Build Coastguard Worker
190*9356374aSAndroid Build Coastguard Worker absl::crc32c_t crc_a = absl::ComputeCrc32c(hello);
191*9356374aSAndroid Build Coastguard Worker absl::crc32c_t crc_b = absl::ComputeCrc32c(world);
192*9356374aSAndroid Build Coastguard Worker absl::crc32c_t crc_ab = absl::ComputeCrc32c(hello_world);
193*9356374aSAndroid Build Coastguard Worker
194*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(absl::RemoveCrc32cSuffix(crc_ab, crc_b, world.size()), crc_a);
195*9356374aSAndroid Build Coastguard Worker }
196*9356374aSAndroid Build Coastguard Worker
TEST(CRC32C,InsertionOperator)197*9356374aSAndroid Build Coastguard Worker TEST(CRC32C, InsertionOperator) {
198*9356374aSAndroid Build Coastguard Worker {
199*9356374aSAndroid Build Coastguard Worker std::ostringstream buf;
200*9356374aSAndroid Build Coastguard Worker buf << absl::crc32c_t{0xc99465aa};
201*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(buf.str(), "c99465aa");
202*9356374aSAndroid Build Coastguard Worker }
203*9356374aSAndroid Build Coastguard Worker {
204*9356374aSAndroid Build Coastguard Worker std::ostringstream buf;
205*9356374aSAndroid Build Coastguard Worker buf << absl::crc32c_t{0};
206*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(buf.str(), "00000000");
207*9356374aSAndroid Build Coastguard Worker }
208*9356374aSAndroid Build Coastguard Worker {
209*9356374aSAndroid Build Coastguard Worker std::ostringstream buf;
210*9356374aSAndroid Build Coastguard Worker buf << absl::crc32c_t{17};
211*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(buf.str(), "00000011");
212*9356374aSAndroid Build Coastguard Worker }
213*9356374aSAndroid Build Coastguard Worker }
214*9356374aSAndroid Build Coastguard Worker
TEST(CRC32C,AbslStringify)215*9356374aSAndroid Build Coastguard Worker TEST(CRC32C, AbslStringify) {
216*9356374aSAndroid Build Coastguard Worker // StrFormat
217*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(absl::StrFormat("%v", absl::crc32c_t{0xc99465aa}), "c99465aa");
218*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(absl::StrFormat("%v", absl::crc32c_t{0}), "00000000");
219*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(absl::StrFormat("%v", absl::crc32c_t{17}), "00000011");
220*9356374aSAndroid Build Coastguard Worker
221*9356374aSAndroid Build Coastguard Worker // StrCat
222*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(absl::StrCat(absl::crc32c_t{0xc99465aa}), "c99465aa");
223*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(absl::StrCat(absl::crc32c_t{0}), "00000000");
224*9356374aSAndroid Build Coastguard Worker EXPECT_EQ(absl::StrCat(absl::crc32c_t{17}), "00000011");
225*9356374aSAndroid Build Coastguard Worker }
226*9356374aSAndroid Build Coastguard Worker
227*9356374aSAndroid Build Coastguard Worker } // namespace
228