pw_kvs: Test cleanup; comment cleanup
- Expand and cleanup comments.
- Address TODO in test. Remove some TODOs that have been addressed.
- Remove outdated, disabled tests in key_value_store_test.cc.
- Enable OffsetRead test and update it to the new Get semantics.
- Make test logging slightly less verbose.
Change-Id: I1453c6ff256be331a483e025b1e4e026dda600d7
diff --git a/pw_kvs/key_value_store.cc b/pw_kvs/key_value_store.cc
index 6c438e8..91b80d9 100644
--- a/pw_kvs/key_value_store.cc
+++ b/pw_kvs/key_value_store.cc
@@ -252,7 +252,6 @@
}
// Scans flash memory within a sector to find a KVS entry magic.
-// TODO(frolv): This needs to be unit tested!
Status KeyValueStore::ScanForEntry(const SectorDescriptor& sector,
Address start_address,
Address* next_entry_address) {
@@ -803,7 +802,6 @@
sector->RemoveWritableBytes(result.size());
if (!result.ok()) {
- // TODO: Once fake flash errors are supported in tests, test this branch.
ERR("Failed to write %zu bytes at %" PRIx32 ". %zu actually written",
entry.size(),
address,
diff --git a/pw_kvs/key_value_store_test.cc b/pw_kvs/key_value_store_test.cc
index 136e548..e914c39 100644
--- a/pw_kvs/key_value_store_test.cc
+++ b/pw_kvs/key_value_store_test.cc
@@ -240,24 +240,6 @@
KeyValueStoreBuffer<kMaxEntries, kMaxUsableSectors> kvs_;
};
-uint16_t CalcKvsCrc(const char* key, const void* data, size_t data_len) {
- uint16_t crc = checksum::CcittCrc16(as_bytes(span(key, std::strlen(key))));
- return checksum::CcittCrc16(span(static_cast<const byte*>(data), data_len),
- crc);
-}
-
-uint16_t CalcTestPartitionCrc() {
- byte buf[16]; // Read as 16 byte chunks
- EXPECT_EQ(sizeof(buf) % test_partition.alignment_bytes(), 0u);
- EXPECT_EQ(test_partition.size_bytes() % sizeof(buf), 0u);
- uint16_t crc = checksum::kCcittCrc16DefaultInitialValue;
- for (size_t i = 0; i < test_partition.size_bytes(); i += sizeof(buf)) {
- test_partition.Read(i, buf);
- crc = checksum::CcittCrc16(as_bytes(span(buf)), crc);
- }
- return crc;
-}
-
} // namespace
TEST_F(EmptyInitializedKvs, Put_SameKeySameValueRepeatedly_AlignedEntries) {
@@ -578,11 +560,11 @@
// Write the same entry many times.
const char* key = "abcd";
- const size_t num_writes = 1; // TODO: Make this > 1 when things work.
+ const size_t num_writes = 99;
uint32_t written_value;
EXPECT_EQ(kvs.size(), (reload == 0) ? 0 : 1u);
for (uint32_t i = 0; i < num_writes; ++i) {
- INF("PUT #%zu for key %s with value %zu", size_t(i), key, size_t(i));
+ DBG("PUT #%zu for key %s with value %zu", size_t(i), key, size_t(i));
written_value = i + 0xfc; // Prevent accidental pass with zero.
EXPECT_OK(kvs.Put(key, written_value));
@@ -590,13 +572,11 @@
}
// Verify that we can read the value back.
- INF("GET final value for key: %s", key);
+ DBG("GET final value for key: %s", key);
uint32_t actual_value;
EXPECT_OK(kvs.Get(key, &actual_value));
EXPECT_EQ(actual_value, written_value);
- kvs.LogDebugInfo();
-
char fname_buf[64] = {'\0'};
snprintf(&fname_buf[0],
sizeof(fname_buf),
@@ -623,13 +603,12 @@
for (size_t i = 0; i < num_writes; ++i) {
StringBuffer<150> key;
key << "key_" << i;
- INF("PUT #%zu for key %s with value %zu", i, key.c_str(), i);
+ DBG("PUT #%zu for key %s with value %zu", i, key.c_str(), i);
size_t value = i + 77; // Prevent accidental pass with zero.
EXPECT_OK(kvs.Put(key.view(), value));
EXPECT_EQ(kvs.size(), i + 1);
}
- kvs.LogDebugInfo();
flash.Dump("WritingMultipleKeysIncreasesSize.bin");
}
@@ -646,12 +625,12 @@
// Add two entries with different keys and values.
const char* key = "Key1";
- INF("PUT value for key: %s", key);
+ DBG("PUT value for key: %s", key);
uint8_t written_value = 0xDA;
ASSERT_OK(kvs.Put(key, written_value));
EXPECT_EQ(kvs.size(), 1u);
- INF("GET value for key: %s", key);
+ DBG("GET value for key: %s", key);
uint8_t actual_value;
ASSERT_OK(kvs.Get(key, &actual_value));
EXPECT_EQ(actual_value, written_value);
@@ -674,23 +653,18 @@
ASSERT_OK(kvs.Init());
// Add two entries with different keys and values.
- INF("PUT first value");
uint8_t value1 = 0xDA;
ASSERT_OK(kvs.Put(key1, as_bytes(span(&value1, sizeof(value1)))));
EXPECT_EQ(kvs.size(), 1u);
- INF("PUT second value");
uint32_t value2 = 0xBAD0301f;
ASSERT_OK(kvs.Put(key2, value2));
EXPECT_EQ(kvs.size(), 2u);
- INF("--------------------------------");
- INF("GET second value");
// Verify data
uint32_t test2;
EXPECT_OK(kvs.Get(key2, &test2));
- INF("GET first value");
uint8_t test1;
ASSERT_OK(kvs.Get(key1, &test1));
@@ -937,14 +911,12 @@
}
}
-#if 0 // Offset reads are not yet supported
-
TEST_F(EmptyInitializedKvs, OffsetRead) {
const char* key = "the_key";
constexpr size_t kReadSize = 16; // needs to be a multiple of alignment
constexpr size_t kTestBufferSize = kReadSize * 10;
ASSERT_GT(buffer.size(), kTestBufferSize);
- ASSERT_LE(kTestBufferSize, 0xFF);
+ ASSERT_LE(kTestBufferSize, 0xFFu);
// Write the entire buffer
for (size_t i = 0; i < kTestBufferSize; i++) {
@@ -956,15 +928,23 @@
// Read in small chunks and verify
for (unsigned i = 0; i < kTestBufferSize / kReadSize; i++) {
std::memset(buffer.data(), 0, buffer.size());
- ASSERT_EQ(
- Status::OK,
- kvs_.Get(key, span(buffer.data(), kReadSize), i * kReadSize).status());
+ StatusWithSize result =
+ kvs_.Get(key, span(buffer.data(), kReadSize), i * kReadSize);
+
+ ASSERT_EQ(kReadSize, result.size());
+
+ // Only last iteration is OK since all remaining data was read.
+ if (i == kTestBufferSize / kReadSize - 1) {
+ ASSERT_EQ(Status::OK, result.status());
+ } else { // RESOURCE_EXHAUSTED, since there is still data to read.
+ ASSERT_EQ(Status::RESOURCE_EXHAUSTED, result.status());
+ }
+
for (unsigned j = 0; j < kReadSize; j++) {
ASSERT_EQ(static_cast<unsigned>(buffer[j]), j + i * kReadSize);
}
}
}
-#endif
TEST_F(EmptyInitializedKvs, MultipleRewrite) {
// Calculate number of elements to ensure multiple sectors are required.
@@ -1200,377 +1180,17 @@
#endif // USE_MEMORY_BUFFER
-TEST_F(EmptyInitializedKvs, DifferentValueSameCrc16) {
- const char kKey[] = "k";
- // With the key and our CRC16 algorithm these both have CRC of 0x82AE
- // Given they are the same size and same key, the KVS will need to check
- // the actual bits to know they are different.
- const char kValue1[] = {'d', 'a', 't'};
- const char kValue2[] = {'u', 'c', 'd'};
-
- // Verify the CRC matches
- ASSERT_EQ(CalcKvsCrc(kKey, kValue1, sizeof(kValue1)),
- CalcKvsCrc(kKey, kValue2, sizeof(kValue2)));
-
- ASSERT_EQ(Status::OK, kvs_.Put(kKey, kValue1));
-
- // Now try to rewrite with the similar value.
- ASSERT_EQ(Status::OK, kvs_.Put(kKey, kValue2));
-
- // Read it back and check it is correct
- char value[3] = {};
- ASSERT_EQ(Status::OK, kvs_.Get(kKey, &value));
- ASSERT_EQ(std::memcmp(value, kValue2, sizeof(value)), 0);
-}
-
-TEST_F(EmptyInitializedKvs, CallingEraseTwice) {
+TEST_F(EmptyInitializedKvs, CallingEraseTwice_NothingWrittenToFlash) {
const uint8_t kValue = 0xDA;
ASSERT_EQ(Status::OK, kvs_.Put(keys[0], kValue));
ASSERT_EQ(Status::OK, kvs_.Delete(keys[0]));
- uint16_t crc = CalcTestPartitionCrc();
+
+ // Compare before / after checksums to verify that nothing was written.
+ const uint16_t crc = checksum::CcittCrc16(test_flash.buffer());
+
EXPECT_EQ(kvs_.Delete(keys[0]), Status::NOT_FOUND);
- // Verify the flash has not changed
- EXPECT_EQ(crc, CalcTestPartitionCrc());
-}
-#if 0 // TODO: not CanFitEntry function yet
-TEST_F(EmptyInitializedKvs, DISABLED_CanFitEntryTests) {
- // Get exactly the number of bytes that can fit in the space remaining for
- // a large value, accounting for alignment.
- constexpr uint16_t kTestKeySize = 2;
- size_t space_remaining =
- test_partition.sector_size_bytes() //
- - RoundUpForAlignment(sizeof(EntryHeader)) // TODO: Sector Header
- - RoundUpForAlignment(sizeof(EntryHeader)) // Cleaning Header
- - RoundUpForAlignment(sizeof(EntryHeader)) // TODO: Chunk Header
- - RoundUpForAlignment(kTestKeySize);
- space_remaining -= test_partition.alignment_bytes() / 2;
- space_remaining = RoundUpForAlignment(space_remaining);
-
- EXPECT_TRUE(kvs_.CanFitEntry(kTestKeySize, space_remaining));
- EXPECT_FALSE(kvs_.CanFitEntry(kTestKeySize, space_remaining + 1));
-}
-#endif
-
-void __attribute__((noinline)) StackHeavyPartialClean() {
-#if 0 // TODO: No FlashSubPartition
-
- ASSERT_GE(test_partition.sector_count(), 2);
- FlashSubPartition test_partition_sector1(&test_partition, 0, 1);
- FlashSubPartition test_partition_sector2(&test_partition, 1, 1);
-
- KeyValueStore kvs1(&test_partition_sector1);
- KeyValueStore kvs2(&test_partition_sector2);
-
- test_partition.Erase(0, test_partition.sector_count());
-
- ASSERT_EQ(Status::OK, kvs1.Enable());
- ASSERT_EQ(Status::OK, kvs2.Enable());
-
- int values1[3] = {100, 101, 102};
- ASSERT_EQ(Status::OK, kvs1.Put(keys[0], values1[0]));
- ASSERT_EQ(Status::OK, kvs1.Put(keys[1], values1[1]));
- ASSERT_EQ(Status::OK, kvs1.Put(keys[2], values1[2]));
-
- int values2[3] = {200, 201, 202};
- ASSERT_EQ(Status::OK, kvs2.Put(keys[0], values2[0]));
- ASSERT_EQ(Status::OK, kvs2.Put(keys[1], values2[1]));
- ASSERT_EQ(Status::OK, kvs2.Delete(keys[1]));
-
- kvs1.Disable();
- kvs2.Disable();
-
- // Key 0 is value1 in first sector, value 2 in second
- // Key 1 is value1 in first sector, erased in second
- // key 2 is only in first sector
-
- uint64_t mark_clean_count = 5;
- ASSERT_EQ(Status::OK,
- PaddedWrite(&test_partition_sector1,
- RoundUpForAlignment(KeyValueStore::kHeaderSize),
- reinterpret_cast<uint8_t*>(&mark_clean_count),
- sizeof(uint64_t)));
-
- // Reset KVS
- kvs_.Disable();
- ASSERT_EQ(Status::OK, kvs_.Init());
- int value;
- ASSERT_EQ(Status::OK, kvs_.Get(keys[0], &value));
- ASSERT_EQ(values2[0], value);
- ASSERT_EQ(kvs_.Get(keys[1], &value), Status::NOT_FOUND);
- ASSERT_EQ(Status::OK, kvs_.Get(keys[2], &value));
- ASSERT_EQ(values1[2], value);
-
- if (test_partition.sector_count() == 2) {
- EXPECT_EQ(kvs_.PendingCleanCount(), 0u);
- // Has forced a clean, mark again for next test
- return; // Not enough sectors to test 2 partial cleans.
- } else {
- EXPECT_EQ(kvs_.PendingCleanCount(), 1u);
- }
-
- mark_clean_count--;
- ASSERT_EQ(Status::OK,
- PaddedWrite(&test_partition_sector2,
- RoundUpForAlignment(KeyValueStore::kHeaderSize),
- reinterpret_cast<uint8_t*>(&mark_clean_count),
- sizeof(uint64_t)));
- // Reset KVS
- kvs_.Disable();
- ASSERT_EQ(Status::OK, kvs_.Init());
- EXPECT_EQ(kvs_.PendingCleanCount(), 2u);
- ASSERT_EQ(Status::OK, kvs_.Get(keys[0], &value));
- ASSERT_EQ(values1[0], value);
- ASSERT_EQ(Status::OK, kvs_.Get(keys[1], &value));
- ASSERT_EQ(values1[1], value);
- ASSERT_EQ(Status::OK, kvs_.Get(keys[2], &value));
- ASSERT_EQ(values1[2], value);
-#endif
-}
-
-// TODO: This doesn't do anything, and would be unreliable anyway.
-size_t CurrentTaskStackFree() { return -1; }
-
-TEST_F(EmptyInitializedKvs, DISABLED_PartialClean) {
- if (CurrentTaskStackFree() < sizeof(KeyValueStore) * 2) {
- PW_LOG_ERROR("Not enough stack for test, skipping");
- return;
- }
- StackHeavyPartialClean();
-}
-
-void __attribute__((noinline)) StackHeavyCleanAll() {
-#if 0 // TODO: no FlashSubPartition
- ASSERT_GE(test_partition.sector_count(), 2);
- FlashSubPartition test_partition_sector1(&test_partition, 0, 1);
-
- KeyValueStore kvs1(&test_partition_sector1);
- test_partition.Erase(0, test_partition.sector_count());
-
- ASSERT_EQ(Status::OK, kvs1.Enable());
-
- int values1[3] = {100, 101, 102};
- ASSERT_EQ(Status::OK, kvs1.Put(keys[0], values1[0]));
- ASSERT_EQ(Status::OK, kvs1.Put(keys[1], values1[1]));
- ASSERT_EQ(Status::OK,
- kvs1.Put(keys[2], values1[2] - 100)); // force a rewrite
- ASSERT_EQ(Status::OK, kvs1.Put(keys[2], values1[2]));
-
- kvs1.Disable();
-
- uint64_t mark_clean_count = 5;
- ASSERT_EQ(Status::OK,
- PaddedWrite(&test_partition_sector1,
- RoundUpForAlignment(KeyValueStore::kHeaderSize),
- reinterpret_cast<uint8_t*>(&mark_clean_count),
- sizeof(uint64_t)));
-
- // Reset KVS
- kvs_.Disable();
- ASSERT_EQ(Status::OK, kvs_.Init());
- int value;
- EXPECT_EQ(kvs_.PendingCleanCount(), 1u);
- ASSERT_EQ(Status::OK, kvs_.CleanAll());
- EXPECT_EQ(kvs_.PendingCleanCount(), 0u);
- ASSERT_EQ(Status::OK, kvs_.Get(keys[0], &value));
- ASSERT_EQ(values1[0], value);
- ASSERT_EQ(Status::OK, kvs_.Get(keys[1], &value));
- ASSERT_EQ(values1[1], value);
- ASSERT_EQ(Status::OK, kvs_.Get(keys[2], &value));
- ASSERT_EQ(values1[2], value);
-#endif
-}
-
-TEST_F(EmptyInitializedKvs, DISABLED_CleanAll) {
- if (CurrentTaskStackFree() < sizeof(KeyValueStore) * 1) {
- PW_LOG_ERROR("Not enough stack for test, skipping");
- return;
- }
- StackHeavyCleanAll();
-}
-
-void __attribute__((noinline)) StackHeavyPartialCleanLargeCounts() {
-#if 0
- ASSERT_GE(test_partition.sector_count(), 2);
- FlashSubPartition test_partition_sector1(&test_partition, 0, 1);
- FlashSubPartition test_partition_sector2(&test_partition, 1, 1);
-
- KeyValueStore kvs1(&test_partition_sector1);
- KeyValueStore kvs2(&test_partition_sector2);
-
- test_partition.Erase(0, test_partition.sector_count());
-
- ASSERT_EQ(Status::OK, kvs1.Enable());
- ASSERT_EQ(Status::OK, kvs2.Enable());
-
- int values1[3] = {100, 101, 102};
- ASSERT_EQ(Status::OK, kvs1.Put(keys[0], values1[0]));
- ASSERT_EQ(Status::OK, kvs1.Put(keys[1], values1[1]));
- ASSERT_EQ(Status::OK, kvs1.Put(keys[2], values1[2]));
-
- int values2[3] = {200, 201, 202};
- ASSERT_EQ(Status::OK, kvs2.Put(keys[0], values2[0]));
- ASSERT_EQ(Status::OK, kvs2.Put(keys[1], values2[1]));
- ASSERT_EQ(Status::OK, kvs2.Delete(keys[1]));
-
- kvs1.Disable();
- kvs2.Disable();
- kvs_.Disable();
-
- // Key 0 is value1 in first sector, value 2 in second
- // Key 1 is value1 in first sector, erased in second
- // key 2 is only in first sector
-
- uint64_t mark_clean_count = 4569877515;
- ASSERT_EQ(Status::OK,
- PaddedWrite(&test_partition_sector1,
- RoundUpForAlignment(KeyValueStore::kHeaderSize),
- reinterpret_cast<uint8_t*>(&mark_clean_count),
- sizeof(uint64_t)));
-
- // Reset KVS
- ASSERT_EQ(Status::OK, kvs_.Init());
- int value;
- ASSERT_EQ(Status::OK, kvs_.Get(keys[0], &value));
- ASSERT_EQ(values2[0], value);
- ASSERT_EQ(kvs_.Get(keys[1], &value), Status::NOT_FOUND);
- ASSERT_EQ(Status::OK, kvs_.Get(keys[2], &value));
- ASSERT_EQ(values1[2], value);
-
- if (test_partition.sector_count() == 2) {
- EXPECT_EQ(kvs_.PendingCleanCount(), 0u);
- // Has forced a clean, mark again for next test
- // Has forced a clean, mark again for next test
- return; // Not enough sectors to test 2 partial cleans.
- } else {
- EXPECT_EQ(kvs_.PendingCleanCount(), 1u);
- }
- kvs_.Disable();
-
- mark_clean_count--;
- ASSERT_EQ(Status::OK,
- PaddedWrite(&test_partition_sector2,
- RoundUpForAlignment(KeyValueStore::kHeaderSize),
- reinterpret_cast<uint8_t*>(&mark_clean_count),
- sizeof(uint64_t)));
- // Reset KVS
- ASSERT_EQ(Status::OK, kvs_.Init());
- EXPECT_EQ(kvs_.PendingCleanCount(), 2u);
- ASSERT_EQ(Status::OK, kvs_.Get(keys[0], &value));
- ASSERT_EQ(values1[0], value);
- ASSERT_EQ(Status::OK, kvs_.Get(keys[1], &value));
- ASSERT_EQ(values1[1], value);
- ASSERT_EQ(Status::OK, kvs_.Get(keys[2], &value));
- ASSERT_EQ(values1[2], value);
-#endif
-}
-
-TEST_F(EmptyInitializedKvs, DISABLED_PartialCleanLargeCounts) {
- if (CurrentTaskStackFree() < sizeof(KeyValueStore) * 2) {
- PW_LOG_ERROR("Not enough stack for test, skipping");
- return;
- }
- StackHeavyPartialCleanLargeCounts();
-}
-
-void __attribute__((noinline)) StackHeavyRecoverNoFreeSectors() {
-#if 0 // TODO: no FlashSubPartition
- ASSERT_GE(test_partition.sector_count(), 2);
- FlashSubPartition test_partition_sector1(&test_partition, 0, 1);
- FlashSubPartition test_partition_sector2(&test_partition, 1, 1);
- FlashSubPartition test_partition_both(&test_partition, 0, 2);
-
- KeyValueStore kvs1(&test_partition_sector1);
- KeyValueStore kvs2(&test_partition_sector2);
- KeyValueStore kvs_both(&test_partition_both);
-
- test_partition.Erase(0, test_partition.sector_count());
-
- ASSERT_EQ(Status::OK, kvs1.Enable());
- ASSERT_EQ(Status::OK, kvs2.Enable());
-
- int values[3] = {100, 101};
- ASSERT_EQ(Status::OK, kvs1.Put(keys[0], values[0]));
- ASSERT_FALSE(kvs1.HasEmptySector());
- ASSERT_EQ(Status::OK, kvs2.Put(keys[1], values[1]));
- ASSERT_FALSE(kvs2.HasEmptySector());
-
- kvs1.Disable();
- kvs2.Disable();
-
- // Reset KVS
- ASSERT_EQ(Status::OK, kvs_both.Enable());
- ASSERT_TRUE(kvs_both.HasEmptySector());
- int value;
- ASSERT_EQ(Status::OK, kvs_both.Get(keys[0], &value));
- ASSERT_EQ(values[0], value);
- ASSERT_EQ(Status::OK, kvs_both.Get(keys[1], &value));
- ASSERT_EQ(values[1], value);
-#endif
-}
-
-TEST_F(EmptyInitializedKvs, RecoverNoFreeSectors) {
- if (CurrentTaskStackFree() < sizeof(KeyValueStore) * 3) {
- PW_LOG_ERROR("Not enough stack for test, skipping");
- return;
- }
- StackHeavyRecoverNoFreeSectors();
-}
-
-void __attribute__((noinline)) StackHeavyCleanOneSector() {
-#if 0 // TODO: no FlashSubPartition
- ASSERT_GE(test_partition.sector_count(), 2);
- FlashSubPartition test_partition_sector1(&test_partition, 0, 1);
- FlashSubPartition test_partition_sector2(&test_partition, 1, 1);
-
- KeyValueStore kvs1(&test_partition_sector1);
-
- test_partition.Erase(0, test_partition.sector_count());
-
- ASSERT_EQ(Status::OK, kvs1.Enable());
-
- int values[3] = {100, 101, 102};
- ASSERT_EQ(Status::OK, kvs1.Put(keys[0], values[0]));
- ASSERT_EQ(Status::OK, kvs1.Put(keys[1], values[1]));
- ASSERT_EQ(Status::OK, kvs1.Put(keys[2], values[2]));
-
- kvs1.Disable();
- kvs_.Disable();
-
- uint64_t mark_clean_count = 1;
- ASSERT_EQ(Status::OK,
- PaddedWrite(&test_partition_sector1,
- RoundUpForAlignment(KeyValueStore::kHeaderSize),
- reinterpret_cast<uint8_t*>(&mark_clean_count),
- sizeof(uint64_t)));
-
- // Reset KVS
- ASSERT_EQ(Status::OK, kvs_.Init());
-
- EXPECT_EQ(kvs_.PendingCleanCount(), 1u);
-
- bool all_sectors_have_been_cleaned = false;
- ASSERT_EQ(Status::OK, kvs_.CleanOneSector(&all_sectors_have_been_cleaned));
- EXPECT_EQ(all_sectors_have_been_cleaned, true);
- EXPECT_EQ(kvs_.PendingCleanCount(), 0u);
- ASSERT_EQ(Status::OK, kvs_.CleanOneSector(&all_sectors_have_been_cleaned));
- EXPECT_EQ(all_sectors_have_been_cleaned, true);
- int value;
- ASSERT_EQ(Status::OK, kvs_.Get(keys[0], &value));
- ASSERT_EQ(values[0], value);
- ASSERT_EQ(Status::OK, kvs_.Get(keys[1], &value));
- ASSERT_EQ(values[1], value);
- ASSERT_EQ(Status::OK, kvs_.Get(keys[2], &value));
- ASSERT_EQ(values[2], value);
-#endif
-}
-
-TEST_F(EmptyInitializedKvs, DISABLED_CleanOneSector) {
- if (CurrentTaskStackFree() < sizeof(KeyValueStore)) {
- PW_LOG_ERROR("Not enough stack for test, skipping");
- return;
- }
- StackHeavyCleanOneSector();
+ EXPECT_EQ(crc, checksum::CcittCrc16(test_flash.buffer()));
}
} // namespace pw::kvs
diff --git a/pw_kvs/public/pw_kvs/flash_memory.h b/pw_kvs/public/pw_kvs/flash_memory.h
index 93ee1eb..05b823f 100644
--- a/pw_kvs/public/pw_kvs/flash_memory.h
+++ b/pw_kvs/public/pw_kvs/flash_memory.h
@@ -203,7 +203,7 @@
// TIMEOUT, on timeout.
// INVALID_ARGUMENT, if address or length is invalid.
// UNKNOWN, on HAL error
- // TODO: StatusWithBool
+ // TODO: Result<bool>
virtual Status IsRegionErased(Address source_flash_address,
size_t len,
bool* is_erased);
diff --git a/pw_kvs/public/pw_kvs/key_value_store.h b/pw_kvs/public/pw_kvs/key_value_store.h
index acd0955..666dd6f 100644
--- a/pw_kvs/public/pw_kvs/key_value_store.h
+++ b/pw_kvs/public/pw_kvs/key_value_store.h
@@ -78,6 +78,7 @@
// value can be read by calling get with an offset.
//
// OK: the entry was successfully read
+ // NOT_FOUND: the key is not present in the KVS
// DATA_LOSS: found the entry, but the data was corrupted
// RESOURCE_EXHAUSTED: the buffer could not fit the entire value, but as
// many bytes as possible were written to it
@@ -120,6 +121,7 @@
//
Status Put(std::string_view key, span<const std::byte> value);
+ // Adds a key-value entry to the KVS, using an object as the value.
template <typename T,
typename = std::enable_if_t<std::is_trivially_copyable_v<T> &&
!std::is_pointer_v<T> &&
@@ -128,8 +130,25 @@
return Put(key, as_bytes(span(&value, 1)));
}
+ // Removes a key-value entry from the KVS.
+ //
+ // OK: the entry was successfully added or updated
+ // NOT_FOUND: the key is not present in the KVS
+ // DATA_LOSS: checksum validation failed after recording the erase
+ // RESOURCE_EXHAUSTED: insufficient space to mark the entry as deleted
+ // FAILED_PRECONDITION: the KVS is not initialized
+ // INVALID_ARGUMENT: key is empty or too long
+ //
Status Delete(std::string_view key);
+ // Returns the size of the value corresponding to the key.
+ //
+ // OK: the size was returned successfully
+ // NOT_FOUND: the key is not present in the KVS
+ // DATA_LOSS: checksum validation failed after reading the entry
+ // FAILED_PRECONDITION: the KVS is not initialized
+ // INVALID_ARGUMENT: key is empty or too long
+ //
StatusWithSize ValueSize(std::string_view key) const;
void LogDebugInfo();