pw_kvs: Implement CRC16 checksum for KVS
- Create CRC16 implementation of pw::kvs::ChecksumAlgorithm.
- Add tests for the ChecksumAlgorithm class.
Change-Id: I3d7268e49c4eec06d61e113602ce24c05a3b0fa0
diff --git a/pw_kvs/BUILD b/pw_kvs/BUILD
index 5433285..69a13ec 100644
--- a/pw_kvs/BUILD
+++ b/pw_kvs/BUILD
@@ -33,6 +33,7 @@
],
hdrs = [
"public/pw_kvs/checksum.h",
+ "public/pw_kvs/crc16_checksum.h",
"public/pw_kvs/flash_memory.h",
"public/pw_kvs/in_memory_fake_flash.h",
"public/pw_kvs/key_value_store.h",
@@ -45,10 +46,33 @@
],
)
+pw_cc_library(
+ name = "crc16",
+ hdrs = [
+ "public/pw_kvs/crc16_checksum.h",
+ ],
+ deps = [
+ ":pw_kvs",
+ "//pw_checksum",
+ ],
+)
+
+pw_cc_test(
+ name = "checksum_test",
+ srcs = ["checksum_test.cc"],
+ deps = [
+ ":crc16",
+ ":pw_kvs",
+ "//pw_checksum",
+ "//pw_log",
+ ],
+)
+
pw_cc_test(
name = "key_value_store_test",
srcs = ["key_value_store_test.cc"],
deps = [
+ ":crc16",
":pw_kvs",
"//pw_checksum",
"//pw_log",
diff --git a/pw_kvs/BUILD.gn b/pw_kvs/BUILD.gn
index 35e02d2..0c17d87 100644
--- a/pw_kvs/BUILD.gn
+++ b/pw_kvs/BUILD.gn
@@ -45,12 +45,38 @@
friend = [ ":key_value_store_test" ]
}
+source_set("crc16") {
+ public = [
+ "public/pw_kvs/crc16_checksum.h",
+ ]
+ sources = public
+ public_deps = [
+ ":pw_kvs",
+ dir_pw_checksum,
+ ]
+}
+
pw_test_group("tests") {
- tests = [ ":key_value_store_test" ]
+ tests = [
+ ":checksum_test",
+ ":key_value_store_test",
+ ]
+}
+
+pw_test("checksum_test") {
+ deps = [
+ ":crc16",
+ ":pw_kvs",
+ dir_pw_log,
+ ]
+ sources = [
+ "checksum_test.cc",
+ ]
}
pw_test("key_value_store_test") {
deps = [
+ ":crc16",
":pw_kvs",
dir_pw_checksum,
dir_pw_log,
diff --git a/pw_kvs/checksum_test.cc b/pw_kvs/checksum_test.cc
new file mode 100644
index 0000000..e5333ad
--- /dev/null
+++ b/pw_kvs/checksum_test.cc
@@ -0,0 +1,58 @@
+// 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(Status::OK, algo.Verify(as_bytes(span(&kStringCrc, 1))));
+}
+
+TEST(Checksum, Verify_Failure) {
+ ChecksumCrc16 algo;
+ EXPECT_EQ(Status::DATA_LOSS, algo.Verify(as_bytes(span(kString.data(), 2))));
+}
+
+TEST(Checksum, Verify_InvalidSize) {
+ ChecksumCrc16 algo;
+ EXPECT_EQ(Status::INVALID_ARGUMENT, algo.Verify({}));
+ EXPECT_EQ(Status::INVALID_ARGUMENT, algo.Verify(as_bytes(span(kString))));
+}
+
+TEST(Checksum, Reset) {
+ ChecksumCrc16 crc_algo;
+ crc_algo.Update(as_bytes(span(kString)));
+ crc_algo.Reset();
+ EXPECT_EQ(crc_algo.state()[0], byte{0xFF});
+ EXPECT_EQ(crc_algo.state()[1], byte{0xFF});
+}
+
+} // namespace
+} // namespace pw::kvs
diff --git a/pw_kvs/key_value_store_test.cc b/pw_kvs/key_value_store_test.cc
index b839d2e..e9baf24 100644
--- a/pw_kvs/key_value_store_test.cc
+++ b/pw_kvs/key_value_store_test.cc
@@ -31,6 +31,7 @@
#include "gtest/gtest.h"
#include "pw_checksum/ccitt_crc16.h"
+#include "pw_kvs/crc16_checksum.h"
#include "pw_kvs/flash_memory.h"
#include "pw_kvs_private/format.h"
#include "pw_kvs_private/macros.h"
@@ -143,8 +144,8 @@
FlashPartition& test_partition = FlashExternalTestPartition();
#endif // USE_MEMORY_BUFFER
-// TODO: Need a checksum implementation (e.g. CRC16) to use for tests.
-constexpr EntryHeaderFormat format{.magic = 0xBAD'C0D3, .checksum = nullptr};
+ChecksumCrc16 checksum;
+constexpr EntryHeaderFormat format{.magic = 0xBAD'C0D3, .checksum = &checksum};
KeyValueStore kvs(&test_partition, format);
diff --git a/pw_kvs/public/pw_kvs/checksum.h b/pw_kvs/public/pw_kvs/checksum.h
index f7b01a1..9f974b3 100644
--- a/pw_kvs/public/pw_kvs/checksum.h
+++ b/pw_kvs/public/pw_kvs/checksum.h
@@ -26,24 +26,24 @@
virtual void Reset() = 0;
// Updates the checksum with the provided data.
- virtual Status Update(span<const std::byte> data_to_checksum) = 0;
+ virtual void Update(span<const std::byte> data) = 0;
- // Convnenience wrapper.
- Status Update(const void* data, size_t size) {
- return Update(span(static_cast<const std::byte*>(data), size));
+ // Update the checksum from a pointer and size.
+ void Update(const void* data, size_t size_bytes) {
+ return Update(span(static_cast<const std::byte*>(data), size_bytes));
}
// Returns the current state of the checksum algorithm.
constexpr const span<const std::byte>& state() const { return state_; }
- // Returns the size of the checksum's state.
+ // Returns the size of the checksum state.
constexpr size_t size_bytes() const { return state_.size(); }
- // Compares a calculated checksum to this checksum's data.
- Status Verify(span<const std::byte> calculated_checksum) const;
+ // Compares a calculated checksum to this checksum's current state.
+ Status Verify(span<const std::byte> checksum) const;
protected:
- // Derived class provides a span of its state buffer.
+ // A derived class provides a span of its state buffer.
constexpr ChecksumAlgorithm(span<const std::byte> state) : state_(state) {}
// Protected destructor prevents deleting ChecksumAlgorithms from the base
diff --git a/pw_kvs/public/pw_kvs/crc16_checksum.h b/pw_kvs/public/pw_kvs/crc16_checksum.h
new file mode 100644
index 0000000..f4e3a9b
--- /dev/null
+++ b/pw_kvs/public/pw_kvs/crc16_checksum.h
@@ -0,0 +1,36 @@
+// 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.
+#pragma once
+
+#include "pw_checksum/ccitt_crc16.h"
+#include "pw_kvs/checksum.h"
+#include "pw_span/span.h"
+
+namespace pw::kvs {
+
+class ChecksumCrc16 final : public ChecksumAlgorithm {
+ public:
+ ChecksumCrc16() : ChecksumAlgorithm(as_bytes(span(&crc_, 1))) {}
+
+ void Reset() final { crc_ = checksum::kCcittCrc16DefaultInitialValue; }
+
+ void Update(span<const std::byte> data) final {
+ crc_ = checksum::CcittCrc16(data, crc_);
+ }
+
+ private:
+ uint16_t crc_ = checksum::kCcittCrc16DefaultInitialValue;
+};
+
+} // namespace pw::kvs