pw_kvs: Check that the flash partition has minimum needed sectors
Verify that the KVS's flash partition has enough sectors to actually
function. That is 1 working sector + 1 free sector, for a minimum
required of 2 sectors.
Change-Id: Ic850bf2c19aa66fa1cc143a433c3f624f292387b
diff --git a/pw_kvs/key_value_store.cc b/pw_kvs/key_value_store.cc
index 84cc4cf..68a8412 100644
--- a/pw_kvs/key_value_store.cc
+++ b/pw_kvs/key_value_store.cc
@@ -70,6 +70,13 @@
return Status::FAILED_PRECONDITION;
}
+ if (partition_.sector_count() < 2) {
+ ERR("KVS init failed: FlashParition sector count (=%u) must be at 2. KVS "
+ "requires at least 1 working sector + 1 free/reserved sector",
+ unsigned(partition_.sector_count()));
+ return Status::FAILED_PRECONDITION;
+ }
+
const size_t sector_size_bytes = partition_.sector_size_bytes();
// TODO: investigate doing this as a static assert/compile-time check.
diff --git a/pw_kvs/key_value_store_binary_format_test.cc b/pw_kvs/key_value_store_binary_format_test.cc
index 4c48e55..079396d 100644
--- a/pw_kvs/key_value_store_binary_format_test.cc
+++ b/pw_kvs/key_value_store_binary_format_test.cc
@@ -157,14 +157,14 @@
constexpr auto kEmpty32Bytes = InitializedBytes<32>(0xff);
static_assert(sizeof(kEmpty32Bytes) == 32);
+EntryFormat default_format = {.magic = kMagic, .checksum = &default_checksum};
+
class KvsErrorHandling : public ::testing::Test {
protected:
KvsErrorHandling()
: flash_(internal::Entry::kMinAlignmentBytes),
partition_(&flash_),
- kvs_(&partition_,
- {.magic = kMagic, .checksum = &default_checksum},
- kNoGcOptions) {}
+ kvs_(&partition_, default_format, kNoGcOptions) {}
void InitFlashTo(span<const byte> contents) {
partition_.Erase();
diff --git a/pw_kvs/key_value_store_test.cc b/pw_kvs/key_value_store_test.cc
index 81238a6..1333364 100644
--- a/pw_kvs/key_value_store_test.cc
+++ b/pw_kvs/key_value_store_test.cc
@@ -630,6 +630,45 @@
EXPECT_EQ(kvs_.size(), 0u);
}
+TEST(InitCheck, TooFewSectors) {
+ // Use test flash with 1 x 4k sectors, 16 byte alignment
+ FakeFlashMemoryBuffer<4 * 1024, 1> test_flash(16);
+ FlashPartition test_partition(&test_flash, 0, test_flash.sector_count());
+
+ constexpr EntryFormat format{.magic = 0xBAD'C0D3, .checksum = nullptr};
+ KeyValueStoreBuffer<kMaxEntries, kMaxUsableSectors> kvs(&test_partition,
+ format);
+
+ EXPECT_EQ(kvs.Init(), Status::FAILED_PRECONDITION);
+}
+
+TEST(InitCheck, ZeroSectors) {
+ // Use test flash with 1 x 4k sectors, 16 byte alignment
+ FakeFlashMemoryBuffer<4 * 1024, 1> test_flash(16);
+
+ // Set FlashPartition to have 0 sectors.
+ FlashPartition test_partition(&test_flash, 0, 0);
+
+ constexpr EntryFormat format{.magic = 0xBAD'C0D3, .checksum = nullptr};
+ KeyValueStoreBuffer<kMaxEntries, kMaxUsableSectors> kvs(&test_partition,
+ format);
+
+ EXPECT_EQ(kvs.Init(), Status::FAILED_PRECONDITION);
+}
+
+TEST(InitCheck, TooManySectors) {
+ // Use test flash with 1 x 4k sectors, 16 byte alignment
+ FakeFlashMemoryBuffer<4 * 1024, 5> test_flash(16);
+
+ // Set FlashPartition to have 0 sectors.
+ FlashPartition test_partition(&test_flash, 0, test_flash.sector_count());
+
+ constexpr EntryFormat format{.magic = 0xBAD'C0D3, .checksum = nullptr};
+ KeyValueStoreBuffer<kMaxEntries, 2> kvs(&test_partition, format);
+
+ EXPECT_EQ(kvs.Init(), Status::FAILED_PRECONDITION);
+}
+
#define ASSERT_OK(expr) ASSERT_EQ(Status::OK, expr)
#define EXPECT_OK(expr) EXPECT_EQ(Status::OK, expr)