You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
151 lines
4.3 KiB
151 lines
4.3 KiB
// Copyright 2020 The Pigweed Authors
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
|
// use this file except in compliance with the License. You may obtain a copy of
|
|
// the License at
|
|
//
|
|
// https://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
// License for the specific language governing permissions and limitations under
|
|
// the License.
|
|
|
|
#include "pw_kvs/checksum.h"
|
|
|
|
#include "gtest/gtest.h"
|
|
#include "pw_kvs/crc16_checksum.h"
|
|
|
|
namespace pw::kvs {
|
|
namespace {
|
|
|
|
using std::byte;
|
|
|
|
constexpr std::string_view kString =
|
|
"In the beginning the Universe was created. This has made a lot of "
|
|
"people very angry and been widely regarded as a bad move.";
|
|
constexpr uint16_t kStringCrc = 0xC184;
|
|
|
|
TEST(Checksum, UpdateAndVerify) {
|
|
ChecksumCrc16 crc16_algo;
|
|
ChecksumAlgorithm& algo = crc16_algo;
|
|
|
|
algo.Update(kString.data(), kString.size());
|
|
EXPECT_EQ(OkStatus(), algo.Verify(std::as_bytes(std::span(&kStringCrc, 1))));
|
|
}
|
|
|
|
TEST(Checksum, Verify_Failure) {
|
|
ChecksumCrc16 algo;
|
|
EXPECT_EQ(Status::DataLoss(),
|
|
algo.Verify(std::as_bytes(std::span(kString.data(), 2))));
|
|
}
|
|
|
|
TEST(Checksum, Verify_InvalidSize) {
|
|
ChecksumCrc16 algo;
|
|
EXPECT_EQ(Status::InvalidArgument(), algo.Verify({}));
|
|
EXPECT_EQ(Status::InvalidArgument(),
|
|
algo.Verify(std::as_bytes(std::span(kString.substr(0, 1)))));
|
|
}
|
|
|
|
TEST(Checksum, Verify_LargerState_ComparesToTruncatedData) {
|
|
byte crc[3] = {byte{0x84}, byte{0xC1}, byte{0x33}};
|
|
ChecksumCrc16 algo;
|
|
ASSERT_GT(sizeof(crc), algo.size_bytes());
|
|
|
|
algo.Update(std::as_bytes(std::span(kString)));
|
|
|
|
EXPECT_EQ(OkStatus(), algo.Verify(crc));
|
|
}
|
|
|
|
TEST(Checksum, Reset) {
|
|
ChecksumCrc16 crc_algo;
|
|
crc_algo.Update(std::as_bytes(std::span(kString)));
|
|
crc_algo.Reset();
|
|
|
|
std::span state = crc_algo.Finish();
|
|
EXPECT_EQ(state[0], byte{0xFF});
|
|
EXPECT_EQ(state[1], byte{0xFF});
|
|
}
|
|
|
|
TEST(IgnoreChecksum, NeverUpdate_VerifyWithoutData) {
|
|
IgnoreChecksum checksum;
|
|
|
|
EXPECT_EQ(OkStatus(), checksum.Verify({}));
|
|
}
|
|
|
|
TEST(IgnoreChecksum, NeverUpdate_VerifyWithData) {
|
|
IgnoreChecksum checksum;
|
|
|
|
EXPECT_EQ(OkStatus(), checksum.Verify(std::as_bytes(std::span(kString))));
|
|
}
|
|
|
|
TEST(IgnoreChecksum, AfterUpdate_Verify) {
|
|
IgnoreChecksum checksum;
|
|
|
|
checksum.Update(std::as_bytes(std::span(kString)));
|
|
EXPECT_EQ(OkStatus(), checksum.Verify({}));
|
|
}
|
|
|
|
constexpr size_t kAlignment = 10;
|
|
|
|
constexpr std::string_view kData =
|
|
"123456789_123456789_123456789_123456789_123456789_" // 50
|
|
"123456789_123456789_123456789_123456789_123456789_"; // 100
|
|
const std::span<const byte> kBytes = std::as_bytes(std::span(kData));
|
|
|
|
class PickyChecksum final : public AlignedChecksum<kAlignment, 32> {
|
|
public:
|
|
PickyChecksum() : AlignedChecksum(data_), data_{}, size_(0) {}
|
|
|
|
void Reset() override {}
|
|
|
|
void FinalizeAligned() override { EXPECT_EQ(kData.size(), size_); }
|
|
|
|
void UpdateAligned(std::span<const std::byte> data) override {
|
|
ASSERT_EQ(data.size() % kAlignment, 0u);
|
|
EXPECT_EQ(kData.substr(0, data.size()),
|
|
std::string_view(reinterpret_cast<const char*>(data.data()),
|
|
data.size()));
|
|
|
|
std::memcpy(&data_[size_], data.data(), data.size());
|
|
size_ += data.size();
|
|
}
|
|
|
|
private:
|
|
std::byte data_[kData.size()];
|
|
size_t size_;
|
|
};
|
|
|
|
TEST(AlignedChecksum, MaintainsAlignment) {
|
|
PickyChecksum checksum;
|
|
|
|
// Write values smaller than the alignment.
|
|
checksum.Update(kBytes.subspan(0, 1));
|
|
checksum.Update(kBytes.subspan(1, 9));
|
|
|
|
// Write values larger than the alignment but smaller than the buffer.
|
|
checksum.Update(kBytes.subspan(10, 11));
|
|
|
|
// Exactly fill the remainder of the buffer.
|
|
checksum.Update(kBytes.subspan(21, 11));
|
|
|
|
// Fill the buffer more than once.
|
|
checksum.Update(kBytes.subspan(32, 66));
|
|
|
|
// Write nothing.
|
|
checksum.Update(kBytes.subspan(98, 0));
|
|
|
|
// Write the remaining data.
|
|
checksum.Update(kBytes.subspan(98, 2));
|
|
|
|
auto state = checksum.Finish();
|
|
EXPECT_EQ(std::string_view(reinterpret_cast<const char*>(state.data()),
|
|
state.size()),
|
|
kData);
|
|
EXPECT_EQ(OkStatus(), checksum.Verify(kBytes));
|
|
}
|
|
|
|
} // namespace
|
|
} // namespace pw::kvs
|