crc32c_test.cc (7502B)
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 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 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 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 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 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 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 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 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 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 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 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 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