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