1*61c4878aSAndroid Build Coastguard Worker // Copyright 2020 The Pigweed Authors
2*61c4878aSAndroid Build Coastguard Worker //
3*61c4878aSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4*61c4878aSAndroid Build Coastguard Worker // use this file except in compliance with the License. You may obtain a copy of
5*61c4878aSAndroid Build Coastguard Worker // the License at
6*61c4878aSAndroid Build Coastguard Worker //
7*61c4878aSAndroid Build Coastguard Worker // https://www.apache.org/licenses/LICENSE-2.0
8*61c4878aSAndroid Build Coastguard Worker //
9*61c4878aSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*61c4878aSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11*61c4878aSAndroid Build Coastguard Worker // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12*61c4878aSAndroid Build Coastguard Worker // License for the specific language governing permissions and limitations under
13*61c4878aSAndroid Build Coastguard Worker // the License.
14*61c4878aSAndroid Build Coastguard Worker #include "pw_checksum/crc32.h"
15*61c4878aSAndroid Build Coastguard Worker
16*61c4878aSAndroid Build Coastguard Worker #include <string_view>
17*61c4878aSAndroid Build Coastguard Worker
18*61c4878aSAndroid Build Coastguard Worker #include "public/pw_checksum/crc32.h"
19*61c4878aSAndroid Build Coastguard Worker #include "pw_bytes/array.h"
20*61c4878aSAndroid Build Coastguard Worker #include "pw_span/span.h"
21*61c4878aSAndroid Build Coastguard Worker #include "pw_unit_test/framework.h"
22*61c4878aSAndroid Build Coastguard Worker
23*61c4878aSAndroid Build Coastguard Worker namespace pw::checksum {
24*61c4878aSAndroid Build Coastguard Worker namespace {
25*61c4878aSAndroid Build Coastguard Worker
26*61c4878aSAndroid Build Coastguard Worker // The expected CRC32 values were calculated using
27*61c4878aSAndroid Build Coastguard Worker //
28*61c4878aSAndroid Build Coastguard Worker // http://www.sunshine2k.de/coding/javascript/crc/crc_js.html
29*61c4878aSAndroid Build Coastguard Worker //
30*61c4878aSAndroid Build Coastguard Worker // with polynomial 0x4C11DB7, initial value 0xFFFFFFFF.
31*61c4878aSAndroid Build Coastguard Worker
32*61c4878aSAndroid Build Coastguard Worker constexpr auto kBytes = bytes::Array<1, 2, 3, 4, 5, 6, 7, 8, 9>();
33*61c4878aSAndroid Build Coastguard Worker constexpr auto kBytesPart0 = bytes::Array<1, 2, 3, 4, 5>();
34*61c4878aSAndroid Build Coastguard Worker constexpr auto kBytesPart1 = bytes::Array<6, 7, 8, 9>();
35*61c4878aSAndroid Build Coastguard Worker constexpr uint32_t kBufferCrc = 0x40EFAB9E;
36*61c4878aSAndroid Build Coastguard Worker
37*61c4878aSAndroid Build Coastguard Worker constexpr std::string_view kString =
38*61c4878aSAndroid Build Coastguard Worker "In the beginning the Universe was created. This has made a lot of "
39*61c4878aSAndroid Build Coastguard Worker "people very angry and been widely regarded as a bad move.";
40*61c4878aSAndroid Build Coastguard Worker constexpr uint32_t kStringCrc = 0x9EC87F88;
41*61c4878aSAndroid Build Coastguard Worker
TEST(Crc32,Empty)42*61c4878aSAndroid Build Coastguard Worker TEST(Crc32, Empty) {
43*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(Crc32::Calculate(span<std::byte>()), PW_CHECKSUM_EMPTY_CRC32);
44*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(Crc32EightBit::Calculate(span<std::byte>()),
45*61c4878aSAndroid Build Coastguard Worker PW_CHECKSUM_EMPTY_CRC32);
46*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(Crc32FourBit::Calculate(span<std::byte>()),
47*61c4878aSAndroid Build Coastguard Worker PW_CHECKSUM_EMPTY_CRC32);
48*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(Crc32OneBit::Calculate(span<std::byte>()), PW_CHECKSUM_EMPTY_CRC32);
49*61c4878aSAndroid Build Coastguard Worker }
50*61c4878aSAndroid Build Coastguard Worker
TEST(Crc32,Buffer)51*61c4878aSAndroid Build Coastguard Worker TEST(Crc32, Buffer) {
52*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(Crc32::Calculate(as_bytes(span(kBytes))), kBufferCrc);
53*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(Crc32EightBit::Calculate(as_bytes(span(kBytes))), kBufferCrc);
54*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(Crc32FourBit::Calculate(as_bytes(span(kBytes))), kBufferCrc);
55*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(Crc32OneBit::Calculate(as_bytes(span(kBytes))), kBufferCrc);
56*61c4878aSAndroid Build Coastguard Worker }
57*61c4878aSAndroid Build Coastguard Worker
TEST(Crc32,String)58*61c4878aSAndroid Build Coastguard Worker TEST(Crc32, String) {
59*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(Crc32::Calculate(as_bytes(span(kString))), kStringCrc);
60*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(Crc32EightBit::Calculate(as_bytes(span(kString))), kStringCrc);
61*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(Crc32FourBit::Calculate(as_bytes(span(kString))), kStringCrc);
62*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(Crc32OneBit::Calculate(as_bytes(span(kString))), kStringCrc);
63*61c4878aSAndroid Build Coastguard Worker }
64*61c4878aSAndroid Build Coastguard Worker
65*61c4878aSAndroid Build Coastguard Worker template <typename CrcVariant>
TestByByte()66*61c4878aSAndroid Build Coastguard Worker void TestByByte() {
67*61c4878aSAndroid Build Coastguard Worker CrcVariant crc;
68*61c4878aSAndroid Build Coastguard Worker for (std::byte b : kBytes) {
69*61c4878aSAndroid Build Coastguard Worker crc.Update(b);
70*61c4878aSAndroid Build Coastguard Worker }
71*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(crc.value(), kBufferCrc);
72*61c4878aSAndroid Build Coastguard Worker }
73*61c4878aSAndroid Build Coastguard Worker
TEST(Crc32Class,ByteByByte)74*61c4878aSAndroid Build Coastguard Worker TEST(Crc32Class, ByteByByte) {
75*61c4878aSAndroid Build Coastguard Worker TestByByte<Crc32>();
76*61c4878aSAndroid Build Coastguard Worker TestByByte<Crc32EightBit>();
77*61c4878aSAndroid Build Coastguard Worker TestByByte<Crc32FourBit>();
78*61c4878aSAndroid Build Coastguard Worker TestByByte<Crc32OneBit>();
79*61c4878aSAndroid Build Coastguard Worker }
80*61c4878aSAndroid Build Coastguard Worker
81*61c4878aSAndroid Build Coastguard Worker template <typename CrcVariant>
TestBuffer()82*61c4878aSAndroid Build Coastguard Worker void TestBuffer() {
83*61c4878aSAndroid Build Coastguard Worker CrcVariant crc32;
84*61c4878aSAndroid Build Coastguard Worker crc32.Update(as_bytes(span(kBytes)));
85*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(crc32.value(), kBufferCrc);
86*61c4878aSAndroid Build Coastguard Worker }
87*61c4878aSAndroid Build Coastguard Worker
TEST(Crc32Class,Buffer)88*61c4878aSAndroid Build Coastguard Worker TEST(Crc32Class, Buffer) {
89*61c4878aSAndroid Build Coastguard Worker TestBuffer<Crc32>();
90*61c4878aSAndroid Build Coastguard Worker TestBuffer<Crc32EightBit>();
91*61c4878aSAndroid Build Coastguard Worker TestBuffer<Crc32FourBit>();
92*61c4878aSAndroid Build Coastguard Worker TestBuffer<Crc32OneBit>();
93*61c4878aSAndroid Build Coastguard Worker }
94*61c4878aSAndroid Build Coastguard Worker
95*61c4878aSAndroid Build Coastguard Worker template <typename CrcVariant>
TestBufferAppend()96*61c4878aSAndroid Build Coastguard Worker void TestBufferAppend() {
97*61c4878aSAndroid Build Coastguard Worker CrcVariant crc32;
98*61c4878aSAndroid Build Coastguard Worker crc32.Update(kBytesPart0);
99*61c4878aSAndroid Build Coastguard Worker crc32.Update(kBytesPart1);
100*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(crc32.value(), kBufferCrc);
101*61c4878aSAndroid Build Coastguard Worker }
102*61c4878aSAndroid Build Coastguard Worker
TEST(Crc32Class,BufferAppend)103*61c4878aSAndroid Build Coastguard Worker TEST(Crc32Class, BufferAppend) {
104*61c4878aSAndroid Build Coastguard Worker TestBufferAppend<Crc32>();
105*61c4878aSAndroid Build Coastguard Worker TestBufferAppend<Crc32EightBit>();
106*61c4878aSAndroid Build Coastguard Worker TestBufferAppend<Crc32FourBit>();
107*61c4878aSAndroid Build Coastguard Worker TestBufferAppend<Crc32OneBit>();
108*61c4878aSAndroid Build Coastguard Worker }
109*61c4878aSAndroid Build Coastguard Worker
110*61c4878aSAndroid Build Coastguard Worker template <typename CrcVariant>
TestString()111*61c4878aSAndroid Build Coastguard Worker void TestString() {
112*61c4878aSAndroid Build Coastguard Worker CrcVariant crc32;
113*61c4878aSAndroid Build Coastguard Worker crc32.Update(as_bytes(span(kString)));
114*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(crc32.value(), kStringCrc);
115*61c4878aSAndroid Build Coastguard Worker }
116*61c4878aSAndroid Build Coastguard Worker
TEST(Crc32Class,String)117*61c4878aSAndroid Build Coastguard Worker TEST(Crc32Class, String) {
118*61c4878aSAndroid Build Coastguard Worker TestString<Crc32>();
119*61c4878aSAndroid Build Coastguard Worker TestString<Crc32EightBit>();
120*61c4878aSAndroid Build Coastguard Worker TestString<Crc32FourBit>();
121*61c4878aSAndroid Build Coastguard Worker TestString<Crc32OneBit>();
122*61c4878aSAndroid Build Coastguard Worker }
123*61c4878aSAndroid Build Coastguard Worker
124*61c4878aSAndroid Build Coastguard Worker extern "C" uint32_t CallChecksumCrc32(const void* data, size_t size_bytes);
125*61c4878aSAndroid Build Coastguard Worker extern "C" uint32_t CallChecksumCrc32Append(const void* data,
126*61c4878aSAndroid Build Coastguard Worker size_t size_bytes,
127*61c4878aSAndroid Build Coastguard Worker uint32_t value);
128*61c4878aSAndroid Build Coastguard Worker
TEST(Crc32FromC,Buffer)129*61c4878aSAndroid Build Coastguard Worker TEST(Crc32FromC, Buffer) {
130*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(CallChecksumCrc32(kBytes.data(), kBytes.size()), kBufferCrc);
131*61c4878aSAndroid Build Coastguard Worker }
132*61c4878aSAndroid Build Coastguard Worker
TEST(Crc32FromC,String)133*61c4878aSAndroid Build Coastguard Worker TEST(Crc32FromC, String) {
134*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(CallChecksumCrc32(kString.data(), kString.size()), kStringCrc);
135*61c4878aSAndroid Build Coastguard Worker }
136*61c4878aSAndroid Build Coastguard Worker
TEST(Crc32AppendFromC,Buffer)137*61c4878aSAndroid Build Coastguard Worker TEST(Crc32AppendFromC, Buffer) {
138*61c4878aSAndroid Build Coastguard Worker uint32_t crc = PW_CHECKSUM_EMPTY_CRC32;
139*61c4878aSAndroid Build Coastguard Worker for (std::byte b : kBytes) {
140*61c4878aSAndroid Build Coastguard Worker crc = CallChecksumCrc32Append(&b, 1, crc);
141*61c4878aSAndroid Build Coastguard Worker }
142*61c4878aSAndroid Build Coastguard Worker
143*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(crc, kBufferCrc);
144*61c4878aSAndroid Build Coastguard Worker }
145*61c4878aSAndroid Build Coastguard Worker
TEST(Crc32AppendFromC,String)146*61c4878aSAndroid Build Coastguard Worker TEST(Crc32AppendFromC, String) {
147*61c4878aSAndroid Build Coastguard Worker EXPECT_EQ(CallChecksumCrc32Append(
148*61c4878aSAndroid Build Coastguard Worker kString.data(), kString.size(), PW_CHECKSUM_EMPTY_CRC32),
149*61c4878aSAndroid Build Coastguard Worker kStringCrc);
150*61c4878aSAndroid Build Coastguard Worker }
151*61c4878aSAndroid Build Coastguard Worker
152*61c4878aSAndroid Build Coastguard Worker } // namespace
153*61c4878aSAndroid Build Coastguard Worker } // namespace pw::checksum
154