Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1 | // Copyright 2020 The Pigweed Authors |
| 2 | // |
| 3 | // Licensed under the Apache License, Version 2.0 (the "License"); you may not |
| 4 | // use this file except in compliance with the License. You may obtain a copy of |
| 5 | // the License at |
| 6 | // |
| 7 | // https://www.apache.org/licenses/LICENSE-2.0 |
| 8 | // |
| 9 | // Unless required by applicable law or agreed to in writing, software |
| 10 | // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
| 11 | // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
| 12 | // License for the specific language governing permissions and limitations under |
| 13 | // the License. |
| 14 | |
| 15 | #include "pw_kvs/key_value_store.h" |
| 16 | |
Wyatt Hepler | acaacf9 | 2020-01-24 10:58:30 -0800 | [diff] [blame] | 17 | #include <array> |
| 18 | #include <cstdio> |
Keir Mierle | 8c352dc | 2020-02-02 13:58:19 -0800 | [diff] [blame] | 19 | #if defined(__linux__) |
| 20 | #include <vector> |
| 21 | #endif // defined(__linux__) |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 22 | #include <cstring> |
| 23 | #include <type_traits> |
Wyatt Hepler | acaacf9 | 2020-01-24 10:58:30 -0800 | [diff] [blame] | 24 | |
Wyatt Hepler | 2ad6067 | 2020-01-21 08:00:16 -0800 | [diff] [blame] | 25 | #include "pw_span/span.h" |
| 26 | |
Keir Mierle | 8c352dc | 2020-02-02 13:58:19 -0800 | [diff] [blame] | 27 | #define PW_LOG_USE_ULTRA_SHORT_NAMES 1 |
| 28 | #include "pw_log/log.h" |
| 29 | |
Wyatt Hepler | 2ad6067 | 2020-01-21 08:00:16 -0800 | [diff] [blame] | 30 | #define USE_MEMORY_BUFFER 1 |
| 31 | |
| 32 | #include "gtest/gtest.h" |
| 33 | #include "pw_checksum/ccitt_crc16.h" |
Wyatt Hepler | ec4b935 | 2020-01-31 15:51:50 -0800 | [diff] [blame] | 34 | #include "pw_kvs/crc16_checksum.h" |
Wyatt Hepler | 2ad6067 | 2020-01-21 08:00:16 -0800 | [diff] [blame] | 35 | #include "pw_kvs/flash_memory.h" |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 36 | #include "pw_kvs_private/format.h" |
| 37 | #include "pw_kvs_private/macros.h" |
| 38 | #include "pw_log/log.h" |
Wyatt Hepler | 2ad6067 | 2020-01-21 08:00:16 -0800 | [diff] [blame] | 39 | #include "pw_status/status.h" |
Keir Mierle | 8c352dc | 2020-02-02 13:58:19 -0800 | [diff] [blame] | 40 | #include "pw_string/string_builder.h" |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 41 | |
| 42 | #if USE_MEMORY_BUFFER |
Wyatt Hepler | 2ad6067 | 2020-01-21 08:00:16 -0800 | [diff] [blame] | 43 | #include "pw_kvs/in_memory_fake_flash.h" |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 44 | #endif // USE_MEMORY_BUFFER |
| 45 | |
Wyatt Hepler | 2ad6067 | 2020-01-21 08:00:16 -0800 | [diff] [blame] | 46 | namespace pw::kvs { |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 47 | namespace { |
| 48 | |
Wyatt Hepler | acaacf9 | 2020-01-24 10:58:30 -0800 | [diff] [blame] | 49 | using std::byte; |
| 50 | |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 51 | template <typename... Args> |
| 52 | constexpr auto ByteArray(Args... args) { |
| 53 | return std::array<byte, sizeof...(args)>{static_cast<byte>(args)...}; |
| 54 | } |
Wyatt Hepler | acaacf9 | 2020-01-24 10:58:30 -0800 | [diff] [blame] | 55 | |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 56 | // Test that the ConvertsToSpan trait correctly idenitifies types that convert |
| 57 | // to span. |
| 58 | static_assert(!ConvertsToSpan<int>()); |
| 59 | static_assert(!ConvertsToSpan<void>()); |
| 60 | static_assert(!ConvertsToSpan<std::byte>()); |
| 61 | static_assert(!ConvertsToSpan<std::byte*>()); |
| 62 | |
| 63 | static_assert(ConvertsToSpan<std::array<int, 5>>()); |
| 64 | static_assert(ConvertsToSpan<decltype("Hello!")>()); |
| 65 | |
| 66 | static_assert(ConvertsToSpan<std::string_view>()); |
| 67 | static_assert(ConvertsToSpan<std::string_view&>()); |
| 68 | static_assert(ConvertsToSpan<std::string_view&&>()); |
| 69 | |
| 70 | static_assert(ConvertsToSpan<const std::string_view>()); |
| 71 | static_assert(ConvertsToSpan<const std::string_view&>()); |
| 72 | static_assert(ConvertsToSpan<const std::string_view&&>()); |
| 73 | |
| 74 | static_assert(ConvertsToSpan<span<int>>()); |
| 75 | static_assert(ConvertsToSpan<span<byte>>()); |
| 76 | static_assert(ConvertsToSpan<span<const int*>>()); |
| 77 | static_assert(ConvertsToSpan<span<bool>&&>()); |
| 78 | static_assert(ConvertsToSpan<const span<bool>&>()); |
| 79 | static_assert(ConvertsToSpan<span<bool>&&>()); |
Wyatt Hepler | acaacf9 | 2020-01-24 10:58:30 -0800 | [diff] [blame] | 80 | |
Keir Mierle | 8c352dc | 2020-02-02 13:58:19 -0800 | [diff] [blame] | 81 | // This is a self contained flash unit with both memory and a single partition. |
| 82 | template <uint32_t sector_size_bytes, uint16_t sector_count> |
| 83 | struct FlashWithPartitionFake { |
| 84 | // Default to 16 byte alignment, which is common in practice. |
| 85 | FlashWithPartitionFake() : FlashWithPartitionFake(16) {} |
| 86 | FlashWithPartitionFake(size_t alignment_bytes) |
| 87 | : memory(alignment_bytes), partition(&memory, 0, memory.sector_count()) {} |
| 88 | |
| 89 | InMemoryFakeFlash<sector_size_bytes, sector_count> memory; |
| 90 | FlashPartition partition; |
| 91 | |
| 92 | public: |
| 93 | #if defined(__linux__) |
| 94 | Status Dump(const char* filename) { |
| 95 | std::FILE* out_file = std::fopen(filename, "w+"); |
| 96 | if (out_file == nullptr) { |
| 97 | PW_LOG_ERROR("Failed to dump to %s", filename); |
| 98 | return Status::DATA_LOSS; |
| 99 | } |
| 100 | std::vector<std::byte> out_vec(memory.size_bytes()); |
| 101 | Status status = |
| 102 | memory.Read(0, pw::span<std::byte>(out_vec.data(), out_vec.size())); |
| 103 | if (status != Status::OK) { |
| 104 | fclose(out_file); |
| 105 | return status; |
| 106 | } |
| 107 | |
| 108 | size_t written = |
| 109 | std::fwrite(out_vec.data(), 1, memory.size_bytes(), out_file); |
| 110 | if (written != memory.size_bytes()) { |
| 111 | PW_LOG_ERROR("Failed to dump to %s, written=%u", |
| 112 | filename, |
| 113 | static_cast<unsigned>(written)); |
| 114 | status = Status::DATA_LOSS; |
| 115 | } else { |
| 116 | PW_LOG_INFO("Dumped to %s", filename); |
| 117 | status = Status::OK; |
| 118 | } |
| 119 | |
| 120 | fclose(out_file); |
| 121 | return status; |
| 122 | } |
| 123 | #else |
| 124 | Status Dump(const char* filename) { |
| 125 | (void)(filename); |
| 126 | return Status::OK; |
| 127 | } |
| 128 | #endif // defined(__linux__) |
| 129 | }; |
| 130 | |
| 131 | typedef FlashWithPartitionFake<4 * 128 /*sector size*/, 6 /*sectors*/> Flash; |
| 132 | |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 133 | #if USE_MEMORY_BUFFER |
| 134 | // Although it might be useful to test other configurations, some tests require |
| 135 | // at least 3 sectors; therfore it should have this when checked in. |
| 136 | InMemoryFakeFlash<4 * 1024, 4> test_flash( |
| 137 | 16); // 4 x 4k sectors, 16 byte alignment |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 138 | FlashPartition test_partition(&test_flash, 0, test_flash.sector_count()); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 139 | InMemoryFakeFlash<1024, 60> large_test_flash(8); |
| 140 | FlashPartition large_test_partition(&large_test_flash, |
| 141 | 0, |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 142 | large_test_flash.sector_count()); |
Wyatt Hepler | 2ad6067 | 2020-01-21 08:00:16 -0800 | [diff] [blame] | 143 | #else // TODO: Test with real flash |
| 144 | FlashPartition& test_partition = FlashExternalTestPartition(); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 145 | #endif // USE_MEMORY_BUFFER |
| 146 | |
Wyatt Hepler | acaacf9 | 2020-01-24 10:58:30 -0800 | [diff] [blame] | 147 | std::array<byte, 512> buffer; |
| 148 | constexpr std::array<const char*, 3> keys{"TestKey1", "Key2", "TestKey3"}; |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 149 | |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 150 | ChecksumCrc16 checksum; |
| 151 | constexpr EntryHeaderFormat format{.magic = 0xBAD'C0D3, .checksum = &checksum}; |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 152 | |
| 153 | size_t RoundUpForAlignment(size_t size) { |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 154 | // TODO: THIS IS SO PADDEDWRITE APPEARS USED |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 155 | uint16_t alignment = test_partition.alignment_bytes(); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 156 | if (size % alignment != 0) { |
| 157 | return size + alignment - size % alignment; |
| 158 | } |
| 159 | return size; |
| 160 | } |
| 161 | |
| 162 | // This class gives attributes of KVS that we are testing against |
| 163 | class KvsAttributes { |
| 164 | public: |
| 165 | KvsAttributes(size_t key_size, size_t data_size) |
| 166 | : sector_header_meta_size_( |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 167 | RoundUpForAlignment(sizeof(EntryHeader))), // TODO: not correct |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 168 | sector_header_clean_size_( |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 169 | RoundUpForAlignment(sizeof(EntryHeader))), // TODO: not correct |
| 170 | chunk_header_size_(RoundUpForAlignment(sizeof(EntryHeader))), |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 171 | data_size_(RoundUpForAlignment(data_size)), |
| 172 | key_size_(RoundUpForAlignment(key_size)), |
| 173 | erase_size_(chunk_header_size_ + key_size_), |
| 174 | min_put_size_(chunk_header_size_ + key_size_ + data_size_) {} |
| 175 | |
| 176 | size_t SectorHeaderSize() { |
| 177 | return sector_header_meta_size_ + sector_header_clean_size_; |
| 178 | } |
| 179 | size_t SectorHeaderMetaSize() { return sector_header_meta_size_; } |
| 180 | size_t ChunkHeaderSize() { return chunk_header_size_; } |
| 181 | size_t DataSize() { return data_size_; } |
| 182 | size_t KeySize() { return key_size_; } |
| 183 | size_t EraseSize() { return erase_size_; } |
| 184 | size_t MinPutSize() { return min_put_size_; } |
| 185 | |
| 186 | private: |
| 187 | const size_t sector_header_meta_size_; |
| 188 | const size_t sector_header_clean_size_; |
| 189 | const size_t chunk_header_size_; |
| 190 | const size_t data_size_; |
| 191 | const size_t key_size_; |
| 192 | const size_t erase_size_; |
| 193 | const size_t min_put_size_; |
| 194 | }; |
| 195 | |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 196 | // Use test fixture for logging support |
| 197 | class KeyValueStoreTest : public ::testing::Test { |
| 198 | protected: |
| 199 | KeyValueStoreTest() : kvs_(&test_partition, format) { |
| 200 | test_partition.Erase(0, test_partition.sector_count()); |
| 201 | ASSERT_EQ(Status::OK, kvs_.Init()); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 202 | } |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 203 | |
| 204 | // Intention of this is to put and erase key-val to fill up sectors. It's a |
| 205 | // helper function in testing how KVS handles cases where flash sector is full |
| 206 | // or near full. |
| 207 | void FillKvs(const char* key, size_t size_to_fill) { |
| 208 | constexpr size_t kTestDataSize = 8; |
| 209 | KvsAttributes kvs_attr(std::strlen(key), kTestDataSize); |
| 210 | const size_t kMaxPutSize = |
| 211 | buffer.size() + kvs_attr.ChunkHeaderSize() + kvs_attr.KeySize(); |
| 212 | |
| 213 | ASSERT_GE(size_to_fill, kvs_attr.MinPutSize() + kvs_attr.EraseSize()); |
| 214 | |
| 215 | // Saving enough space to perform erase after loop |
| 216 | size_to_fill -= kvs_attr.EraseSize(); |
| 217 | // We start with possible small chunk to prevent too small of a Kvs.Put() at |
| 218 | // the end. |
| 219 | size_t chunk_len = |
| 220 | std::max(kvs_attr.MinPutSize(), size_to_fill % buffer.size()); |
| 221 | std::memset(buffer.data(), 0, buffer.size()); |
| 222 | while (size_to_fill > 0) { |
| 223 | // Changing buffer value so put actually does something |
| 224 | buffer[0] = static_cast<byte>(static_cast<uint8_t>(buffer[0]) + 1); |
| 225 | ASSERT_EQ(Status::OK, |
| 226 | kvs_.Put(key, |
| 227 | span(buffer.data(), |
| 228 | chunk_len - kvs_attr.ChunkHeaderSize() - |
| 229 | kvs_attr.KeySize()))); |
| 230 | size_to_fill -= chunk_len; |
| 231 | chunk_len = std::min(size_to_fill, kMaxPutSize); |
| 232 | } |
| 233 | ASSERT_EQ(Status::OK, kvs_.Delete(key)); |
| 234 | } |
| 235 | |
| 236 | KeyValueStore kvs_; |
| 237 | }; |
| 238 | |
| 239 | Status PaddedWrite(FlashPartition* partition, |
| 240 | FlashPartition::Address address, |
| 241 | const std::byte* buf, |
| 242 | size_t size) { |
| 243 | static constexpr size_t kMaxAlignmentBytes = 128; |
| 244 | byte alignment_buffer[kMaxAlignmentBytes] = {}; |
| 245 | |
| 246 | size_t aligned_bytes = size - (size % partition->alignment_bytes()); |
| 247 | TRY(partition->Write(address, span(buf, aligned_bytes))); |
| 248 | |
| 249 | uint16_t remaining_bytes = size - aligned_bytes; |
| 250 | if (remaining_bytes > 0) { |
| 251 | std::memcpy(alignment_buffer, &buf[aligned_bytes], remaining_bytes); |
| 252 | if (Status status = partition->Write( |
| 253 | address + aligned_bytes, |
| 254 | span(alignment_buffer, partition->alignment_bytes())); |
| 255 | !status.ok()) { |
| 256 | return status; |
| 257 | } |
| 258 | } |
| 259 | return Status::OK; |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 260 | } |
| 261 | |
| 262 | uint16_t CalcKvsCrc(const char* key, const void* data, size_t data_len) { |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 263 | // TODO: remove this; it's only to prevent unused function warnings |
| 264 | (void)PaddedWrite; |
| 265 | |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 266 | uint16_t crc = checksum::CcittCrc16(as_bytes(span(key, std::strlen(key)))); |
Wyatt Hepler | acaacf9 | 2020-01-24 10:58:30 -0800 | [diff] [blame] | 267 | return checksum::CcittCrc16(span(static_cast<const byte*>(data), data_len), |
| 268 | crc); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 269 | } |
| 270 | |
| 271 | uint16_t CalcTestPartitionCrc() { |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 272 | byte buf[16]; // Read as 16 byte chunks |
| 273 | EXPECT_EQ(sizeof(buf) % test_partition.alignment_bytes(), 0u); |
| 274 | EXPECT_EQ(test_partition.size_bytes() % sizeof(buf), 0u); |
Wyatt Hepler | 2ad6067 | 2020-01-21 08:00:16 -0800 | [diff] [blame] | 275 | uint16_t crc = checksum::kCcittCrc16DefaultInitialValue; |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 276 | for (size_t i = 0; i < test_partition.size_bytes(); i += sizeof(buf)) { |
| 277 | test_partition.Read(i, buf); |
Wyatt Hepler | 2ad6067 | 2020-01-21 08:00:16 -0800 | [diff] [blame] | 278 | crc = checksum::CcittCrc16(as_bytes(span(buf)), crc); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 279 | } |
Wyatt Hepler | 2ad6067 | 2020-01-21 08:00:16 -0800 | [diff] [blame] | 280 | return crc; |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 281 | } |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 282 | |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 283 | } // namespace |
| 284 | |
Wyatt Hepler | 6c24c06 | 2020-02-05 15:30:49 -0800 | [diff] [blame^] | 285 | TEST_F(KeyValueStoreTest, Delete_GetDeletedKey_ReturnsNotFound) { |
| 286 | ASSERT_EQ(Status::OK, kvs_.Put("kEy", as_bytes(span("123")))); |
| 287 | ASSERT_EQ(Status::OK, kvs_.Delete("kEy")); |
| 288 | |
| 289 | EXPECT_EQ(Status::NOT_FOUND, kvs_.Get("kEy", {}).status()); |
| 290 | } |
| 291 | |
| 292 | TEST_F(KeyValueStoreTest, Delete_AddBackKey_PersistsAfterInitialization) { |
| 293 | ASSERT_EQ(Status::OK, kvs_.Put("kEy", as_bytes(span("123")))); |
| 294 | ASSERT_EQ(Status::OK, kvs_.Delete("kEy")); |
| 295 | |
| 296 | EXPECT_EQ(Status::OK, kvs_.Put("kEy", as_bytes(span("45678")))); |
| 297 | char data[6] = {}; |
| 298 | ASSERT_EQ(Status::OK, kvs_.Get("kEy", &data)); |
| 299 | EXPECT_STREQ(data, "45678"); |
| 300 | |
| 301 | // Ensure that the re-added key is still present after reinitialization. |
| 302 | KeyValueStore new_kvs(&test_partition, format); |
| 303 | ASSERT_EQ(Status::OK, new_kvs.Init()); |
| 304 | |
| 305 | EXPECT_EQ(Status::OK, new_kvs.Put("kEy", as_bytes(span("45678")))); |
| 306 | char new_data[6] = {}; |
| 307 | EXPECT_EQ(Status::OK, new_kvs.Get("kEy", &new_data)); |
| 308 | EXPECT_STREQ(data, "45678"); |
| 309 | } |
| 310 | |
| 311 | TEST_F(KeyValueStoreTest, Delete_AllItems_KvsIsEmpty) { |
| 312 | ASSERT_EQ(Status::OK, kvs_.Put("kEy", as_bytes(span("123")))); |
| 313 | ASSERT_EQ(Status::OK, kvs_.Delete("kEy")); |
| 314 | |
| 315 | EXPECT_EQ(0u, kvs_.size()); |
| 316 | EXPECT_TRUE(kvs_.empty()); |
| 317 | } |
| 318 | |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 319 | TEST_F(KeyValueStoreTest, Iteration_Empty_ByReference) { |
Wyatt Hepler | ce0da52 | 2020-02-04 16:56:44 -0800 | [diff] [blame] | 320 | for (const KeyValueStore::Item& entry : kvs_) { |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 321 | FAIL(); // The KVS is empty; this shouldn't execute. |
| 322 | static_cast<void>(entry); |
| 323 | } |
| 324 | } |
| 325 | |
| 326 | TEST_F(KeyValueStoreTest, Iteration_Empty_ByValue) { |
Wyatt Hepler | ce0da52 | 2020-02-04 16:56:44 -0800 | [diff] [blame] | 327 | for (KeyValueStore::Item entry : kvs_) { |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 328 | FAIL(); // The KVS is empty; this shouldn't execute. |
| 329 | static_cast<void>(entry); |
| 330 | } |
| 331 | } |
| 332 | |
Wyatt Hepler | 6c24c06 | 2020-02-05 15:30:49 -0800 | [diff] [blame^] | 333 | TEST_F(KeyValueStoreTest, Iteration_OneItem) { |
| 334 | char value[] = "123"; |
| 335 | |
| 336 | ASSERT_EQ(Status::OK, kvs_.Put("kEy", as_bytes(span(value)))); |
| 337 | |
| 338 | for (KeyValueStore::Item entry : kvs_) { |
| 339 | EXPECT_STREQ(entry.key().data(), "kEy"); // Make sure null-terminated. |
| 340 | |
| 341 | char buffer[sizeof(value)] = {}; |
| 342 | EXPECT_EQ(Status::OK, entry.Get(&buffer)); |
| 343 | EXPECT_STREQ(value, buffer); |
| 344 | } |
| 345 | } |
| 346 | |
| 347 | TEST_F(KeyValueStoreTest, Iteration_EmptyAfterDeletion) { |
| 348 | ASSERT_EQ(Status::OK, kvs_.Put("kEy", as_bytes(span("123")))); |
| 349 | ASSERT_EQ(Status::OK, kvs_.Delete("kEy")); |
| 350 | |
| 351 | for (KeyValueStore::Item entry : kvs_) { |
| 352 | static_cast<void>(entry); |
| 353 | FAIL(); |
| 354 | } |
| 355 | } |
| 356 | |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 357 | TEST_F(KeyValueStoreTest, DISABLED_FuzzTest) { |
| 358 | if (test_partition.sector_size_bytes() < 4 * 1024 || |
| 359 | test_partition.sector_count() < 4) { |
Wyatt Hepler | 2ad6067 | 2020-01-21 08:00:16 -0800 | [diff] [blame] | 360 | PW_LOG_INFO("Sectors too small, skipping test."); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 361 | return; // TODO: Test could be generalized |
| 362 | } |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 363 | const char* key1 = "Buf1"; |
| 364 | const char* key2 = "Buf2"; |
| 365 | const size_t kLargestBufSize = 3 * 1024; |
Wyatt Hepler | acaacf9 | 2020-01-24 10:58:30 -0800 | [diff] [blame] | 366 | static byte buf1[kLargestBufSize]; |
| 367 | static byte buf2[kLargestBufSize]; |
| 368 | std::memset(buf1, 1, sizeof(buf1)); |
| 369 | std::memset(buf2, 2, sizeof(buf2)); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 370 | |
| 371 | // Start with things in KVS |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 372 | ASSERT_EQ(Status::OK, kvs_.Put(key1, buf1)); |
| 373 | ASSERT_EQ(Status::OK, kvs_.Put(key2, buf2)); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 374 | for (size_t j = 0; j < keys.size(); j++) { |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 375 | ASSERT_EQ(Status::OK, kvs_.Put(keys[j], j)); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 376 | } |
| 377 | |
| 378 | for (size_t i = 0; i < 100; i++) { |
| 379 | // Vary two sizes |
| 380 | size_t size1 = (kLargestBufSize) / (i + 1); |
| 381 | size_t size2 = (kLargestBufSize) / (100 - i); |
| 382 | for (size_t j = 0; j < 50; j++) { |
| 383 | // Rewrite a single key many times, can fill up a sector |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 384 | ASSERT_EQ(Status::OK, kvs_.Put("some_data", j)); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 385 | } |
| 386 | // Delete and re-add everything |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 387 | ASSERT_EQ(Status::OK, kvs_.Delete(key1)); |
| 388 | ASSERT_EQ(Status::OK, kvs_.Put(key1, span(buf1, size1))); |
| 389 | ASSERT_EQ(Status::OK, kvs_.Delete(key2)); |
| 390 | ASSERT_EQ(Status::OK, kvs_.Put(key2, span(buf2, size2))); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 391 | for (size_t j = 0; j < keys.size(); j++) { |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 392 | ASSERT_EQ(Status::OK, kvs_.Delete(keys[j])); |
| 393 | ASSERT_EQ(Status::OK, kvs_.Put(keys[j], j)); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 394 | } |
| 395 | |
| 396 | // Re-enable and verify |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 397 | ASSERT_EQ(Status::OK, kvs_.Init()); |
Wyatt Hepler | acaacf9 | 2020-01-24 10:58:30 -0800 | [diff] [blame] | 398 | static byte buf[4 * 1024]; |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 399 | ASSERT_EQ(Status::OK, kvs_.Get(key1, span(buf, size1)).status()); |
Wyatt Hepler | acaacf9 | 2020-01-24 10:58:30 -0800 | [diff] [blame] | 400 | ASSERT_EQ(std::memcmp(buf, buf1, size1), 0); |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 401 | ASSERT_EQ(Status::OK, kvs_.Get(key2, span(buf, size2)).status()); |
Wyatt Hepler | acaacf9 | 2020-01-24 10:58:30 -0800 | [diff] [blame] | 402 | ASSERT_EQ(std::memcmp(buf2, buf2, size2), 0); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 403 | for (size_t j = 0; j < keys.size(); j++) { |
| 404 | size_t ret = 1000; |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 405 | ASSERT_EQ(Status::OK, kvs_.Get(keys[j], &ret)); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 406 | ASSERT_EQ(ret, j); |
| 407 | } |
| 408 | } |
| 409 | } |
| 410 | |
Wyatt Hepler | 595cf01 | 2020-02-05 09:31:02 -0800 | [diff] [blame] | 411 | TEST_F(KeyValueStoreTest, Basic) { |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 412 | // Add some data |
| 413 | uint8_t value1 = 0xDA; |
Wyatt Hepler | acaacf9 | 2020-01-24 10:58:30 -0800 | [diff] [blame] | 414 | ASSERT_EQ(Status::OK, |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 415 | kvs_.Put(keys[0], as_bytes(span(&value1, sizeof(value1))))); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 416 | |
| 417 | uint32_t value2 = 0xBAD0301f; |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 418 | ASSERT_EQ(Status::OK, kvs_.Put(keys[1], value2)); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 419 | |
| 420 | // Verify data |
| 421 | uint32_t test2; |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 422 | EXPECT_EQ(Status::OK, kvs_.Get(keys[1], &test2)); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 423 | uint8_t test1; |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 424 | ASSERT_EQ(Status::OK, kvs_.Get(keys[0], &test1)); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 425 | |
| 426 | EXPECT_EQ(test1, value1); |
| 427 | EXPECT_EQ(test2, value2); |
| 428 | |
Wyatt Hepler | 6c24c06 | 2020-02-05 15:30:49 -0800 | [diff] [blame^] | 429 | // Delete a key |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 430 | EXPECT_EQ(Status::OK, kvs_.Delete(keys[0])); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 431 | |
| 432 | // Verify it was erased |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 433 | EXPECT_EQ(kvs_.Get(keys[0], &test1), Status::NOT_FOUND); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 434 | test2 = 0; |
Wyatt Hepler | 2ad6067 | 2020-01-21 08:00:16 -0800 | [diff] [blame] | 435 | ASSERT_EQ( |
| 436 | Status::OK, |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 437 | kvs_.Get(keys[1], span(reinterpret_cast<byte*>(&test2), sizeof(test2))) |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 438 | .status()); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 439 | EXPECT_EQ(test2, value2); |
| 440 | |
Wyatt Hepler | 6c24c06 | 2020-02-05 15:30:49 -0800 | [diff] [blame^] | 441 | // Delete other key |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 442 | kvs_.Delete(keys[1]); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 443 | |
| 444 | // Verify it was erased |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 445 | EXPECT_EQ(kvs_.size(), 0u); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 446 | } |
| 447 | |
Keir Mierle | 8c352dc | 2020-02-02 13:58:19 -0800 | [diff] [blame] | 448 | #define ASSERT_OK(expr) ASSERT_EQ(Status::OK, expr) |
| 449 | #define EXPECT_OK(expr) EXPECT_EQ(Status::OK, expr) |
| 450 | |
Wyatt Hepler | 595cf01 | 2020-02-05 09:31:02 -0800 | [diff] [blame] | 451 | TEST(InMemoryKvs, WriteOneKeyMultipleTimes) { |
Keir Mierle | 8c352dc | 2020-02-02 13:58:19 -0800 | [diff] [blame] | 452 | // Create and erase the fake flash. It will persist across reloads. |
| 453 | Flash flash; |
| 454 | ASSERT_OK(flash.partition.Erase()); |
| 455 | |
| 456 | int num_reloads = 2; |
| 457 | for (int reload = 0; reload < num_reloads; ++reload) { |
| 458 | DBG("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"); |
| 459 | DBG("xxx xxxx"); |
| 460 | DBG("xxx Reload %2d xxxx", reload); |
| 461 | DBG("xxx xxxx"); |
| 462 | DBG("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"); |
| 463 | |
| 464 | // Create and initialize the KVS. |
| 465 | constexpr EntryHeaderFormat format{.magic = 0xBAD'C0D3, |
| 466 | .checksum = nullptr}; |
| 467 | KeyValueStore kvs(&flash.partition, format); |
| 468 | ASSERT_OK(kvs.Init()); |
| 469 | |
| 470 | // Write the same entry many times. |
| 471 | const char* key = "abcd"; |
| 472 | const size_t num_writes = 1; // TODO: Make this > 1 when things work. |
| 473 | uint32_t written_value; |
| 474 | EXPECT_EQ(kvs.size(), (reload == 0) ? 0 : 1u); |
| 475 | for (uint32_t i = 0; i < num_writes; ++i) { |
Wyatt Hepler | 6e3a83b | 2020-02-04 07:36:45 -0800 | [diff] [blame] | 476 | INF("PUT #%zu for key %s with value %zu", size_t(i), key, size_t(i)); |
Keir Mierle | 8c352dc | 2020-02-02 13:58:19 -0800 | [diff] [blame] | 477 | |
| 478 | written_value = i + 0xfc; // Prevent accidental pass with zero. |
| 479 | EXPECT_OK(kvs.Put(key, written_value)); |
| 480 | EXPECT_EQ(kvs.size(), 1u); |
| 481 | } |
| 482 | |
| 483 | // Verify that we can read the value back. |
| 484 | INF("GET final value for key: %s", key); |
| 485 | uint32_t actual_value; |
| 486 | EXPECT_OK(kvs.Get(key, &actual_value)); |
| 487 | EXPECT_EQ(actual_value, written_value); |
| 488 | |
| 489 | kvs.LogDebugInfo(); |
| 490 | |
| 491 | char fname_buf[64] = {'\0'}; |
| 492 | snprintf(&fname_buf[0], |
| 493 | sizeof(fname_buf), |
| 494 | "WriteOneKeyMultipleTimes_%d.bin", |
| 495 | reload); |
| 496 | flash.Dump(fname_buf); |
| 497 | } |
| 498 | } |
| 499 | |
| 500 | TEST(InMemoryKvs, WritingMultipleKeysIncreasesSize) { |
| 501 | // Create and erase the fake flash. |
| 502 | Flash flash; |
| 503 | ASSERT_OK(flash.partition.Erase()); |
| 504 | |
| 505 | // Create and initialize the KVS. |
| 506 | constexpr EntryHeaderFormat format{.magic = 0xBAD'C0D3, .checksum = nullptr}; |
| 507 | KeyValueStore kvs(&flash.partition, format); |
| 508 | ASSERT_OK(kvs.Init()); |
| 509 | |
| 510 | // Write the same entry many times. |
| 511 | const size_t num_writes = 10; |
| 512 | EXPECT_EQ(kvs.size(), 0u); |
| 513 | for (size_t i = 0; i < num_writes; ++i) { |
| 514 | StringBuffer<150> key; |
| 515 | key << "key_" << i; |
| 516 | INF("PUT #%zu for key %s with value %zu", i, key.c_str(), i); |
| 517 | |
| 518 | size_t value = i + 77; // Prevent accidental pass with zero. |
| 519 | EXPECT_OK(kvs.Put(key.view(), value)); |
| 520 | EXPECT_EQ(kvs.size(), i + 1); |
| 521 | } |
| 522 | kvs.LogDebugInfo(); |
| 523 | flash.Dump("WritingMultipleKeysIncreasesSize.bin"); |
| 524 | } |
| 525 | |
| 526 | TEST(InMemoryKvs, WriteAndReadOneKey) { |
| 527 | // Create and erase the fake flash. |
| 528 | Flash flash; |
| 529 | ASSERT_OK(flash.partition.Erase()); |
| 530 | |
| 531 | // Create and initialize the KVS. |
| 532 | constexpr EntryHeaderFormat format{.magic = 0xBAD'C0D3, .checksum = nullptr}; |
| 533 | KeyValueStore kvs(&flash.partition, format); |
| 534 | ASSERT_OK(kvs.Init()); |
| 535 | |
| 536 | // Add two entries with different keys and values. |
| 537 | const char* key = "Key1"; |
| 538 | INF("PUT value for key: %s", key); |
| 539 | uint8_t written_value = 0xDA; |
| 540 | ASSERT_OK(kvs.Put(key, written_value)); |
| 541 | EXPECT_EQ(kvs.size(), 1u); |
| 542 | |
| 543 | INF("GET value for key: %s", key); |
| 544 | uint8_t actual_value; |
| 545 | ASSERT_OK(kvs.Get(key, &actual_value)); |
| 546 | EXPECT_EQ(actual_value, written_value); |
| 547 | |
| 548 | EXPECT_EQ(kvs.size(), 1u); |
| 549 | } |
| 550 | |
| 551 | TEST(InMemoryKvs, Basic) { |
| 552 | const char* key1 = "Key1"; |
| 553 | const char* key2 = "Key2"; |
| 554 | |
| 555 | // Create and erase the fake flash. |
| 556 | Flash flash; |
| 557 | ASSERT_EQ(Status::OK, flash.partition.Erase()); |
| 558 | |
| 559 | // Create and initialize the KVS. |
| 560 | constexpr EntryHeaderFormat format{.magic = 0xBAD'C0D3, .checksum = nullptr}; |
| 561 | KeyValueStore kvs(&flash.partition, format); |
| 562 | ASSERT_OK(kvs.Init()); |
| 563 | |
| 564 | // Add two entries with different keys and values. |
| 565 | INF("PUT first value"); |
| 566 | uint8_t value1 = 0xDA; |
| 567 | ASSERT_OK(kvs.Put(key1, as_bytes(span(&value1, sizeof(value1))))); |
| 568 | EXPECT_EQ(kvs.size(), 1u); |
| 569 | |
| 570 | INF("PUT second value"); |
| 571 | uint32_t value2 = 0xBAD0301f; |
| 572 | ASSERT_OK(kvs.Put(key2, value2)); |
| 573 | EXPECT_EQ(kvs.size(), 2u); |
| 574 | |
| 575 | INF("--------------------------------"); |
| 576 | INF("GET second value"); |
| 577 | // Verify data |
| 578 | uint32_t test2; |
| 579 | EXPECT_OK(kvs.Get(key2, &test2)); |
| 580 | |
| 581 | INF("GET first value"); |
| 582 | uint8_t test1; |
| 583 | ASSERT_OK(kvs.Get(key1, &test1)); |
| 584 | |
| 585 | EXPECT_EQ(test1, value1); |
| 586 | EXPECT_EQ(test2, value2); |
| 587 | |
| 588 | EXPECT_EQ(kvs.size(), 2u); |
| 589 | } |
| 590 | |
Wyatt Hepler | 6c24c06 | 2020-02-05 15:30:49 -0800 | [diff] [blame^] | 591 | TEST_F(KeyValueStoreTest, MaxKeyLength) { |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 592 | // Add some data |
| 593 | char key[16] = "123456789abcdef"; // key length 15 (without \0) |
| 594 | int value = 1; |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 595 | ASSERT_EQ(Status::OK, kvs_.Put(key, value)); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 596 | |
| 597 | // Verify data |
| 598 | int test = 0; |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 599 | ASSERT_EQ(Status::OK, kvs_.Get(key, &test)); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 600 | EXPECT_EQ(test, value); |
| 601 | |
Wyatt Hepler | 6c24c06 | 2020-02-05 15:30:49 -0800 | [diff] [blame^] | 602 | // Delete a key |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 603 | kvs_.Delete(key); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 604 | |
| 605 | // Verify it was erased |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 606 | EXPECT_EQ(kvs_.Get(key, &test), Status::NOT_FOUND); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 607 | } |
| 608 | |
Wyatt Hepler | 6c24c06 | 2020-02-05 15:30:49 -0800 | [diff] [blame^] | 609 | TEST_F(KeyValueStoreTest, LargeBuffers) { |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 610 | // Note this assumes that no other keys larger then key0 |
| 611 | static_assert(sizeof(keys[0]) >= sizeof(keys[1]) && |
| 612 | sizeof(keys[0]) >= sizeof(keys[2])); |
| 613 | KvsAttributes kvs_attr(std::strlen(keys[0]), buffer.size()); |
| 614 | |
| 615 | // Verify the data will fit in this test partition. This checks that all the |
| 616 | // keys chunks will fit and a header for each sector will fit. It requires 1 |
| 617 | // empty sector also. |
| 618 | const size_t kAllChunkSize = kvs_attr.MinPutSize() * keys.size(); |
| 619 | const size_t kAllSectorHeaderSizes = |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 620 | kvs_attr.SectorHeaderSize() * (test_partition.sector_count() - 1); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 621 | const size_t kMinSize = kAllChunkSize + kAllSectorHeaderSizes; |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 622 | const size_t kAvailSectorSpace = |
| 623 | test_partition.sector_size_bytes() * (test_partition.sector_count() - 1); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 624 | if (kAvailSectorSpace < kMinSize) { |
Wyatt Hepler | 2ad6067 | 2020-01-21 08:00:16 -0800 | [diff] [blame] | 625 | PW_LOG_INFO("KVS too small, skipping test."); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 626 | return; |
| 627 | } |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 628 | |
| 629 | // Add and verify |
| 630 | for (unsigned add_idx = 0; add_idx < keys.size(); add_idx++) { |
Wyatt Hepler | acaacf9 | 2020-01-24 10:58:30 -0800 | [diff] [blame] | 631 | std::memset(buffer.data(), add_idx, buffer.size()); |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 632 | ASSERT_EQ(Status::OK, kvs_.Put(keys[add_idx], buffer)); |
| 633 | EXPECT_EQ(kvs_.size(), add_idx + 1); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 634 | for (unsigned verify_idx = 0; verify_idx <= add_idx; verify_idx++) { |
Wyatt Hepler | acaacf9 | 2020-01-24 10:58:30 -0800 | [diff] [blame] | 635 | std::memset(buffer.data(), 0, buffer.size()); |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 636 | ASSERT_EQ(Status::OK, kvs_.Get(keys[verify_idx], buffer).status()); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 637 | for (unsigned i = 0; i < buffer.size(); i++) { |
Wyatt Hepler | acaacf9 | 2020-01-24 10:58:30 -0800 | [diff] [blame] | 638 | EXPECT_EQ(static_cast<unsigned>(buffer[i]), verify_idx); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 639 | } |
| 640 | } |
| 641 | } |
| 642 | |
| 643 | // Erase and verify |
| 644 | for (unsigned erase_idx = 0; erase_idx < keys.size(); erase_idx++) { |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 645 | ASSERT_EQ(Status::OK, kvs_.Delete(keys[erase_idx])); |
| 646 | EXPECT_EQ(kvs_.size(), keys.size() - erase_idx - 1); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 647 | for (unsigned verify_idx = 0; verify_idx < keys.size(); verify_idx++) { |
Wyatt Hepler | acaacf9 | 2020-01-24 10:58:30 -0800 | [diff] [blame] | 648 | std::memset(buffer.data(), 0, buffer.size()); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 649 | if (verify_idx <= erase_idx) { |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 650 | ASSERT_EQ(kvs_.Get(keys[verify_idx], buffer).status(), |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 651 | Status::NOT_FOUND); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 652 | } else { |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 653 | ASSERT_EQ(Status::OK, kvs_.Get(keys[verify_idx], buffer).status()); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 654 | for (uint32_t i = 0; i < buffer.size(); i++) { |
Wyatt Hepler | acaacf9 | 2020-01-24 10:58:30 -0800 | [diff] [blame] | 655 | EXPECT_EQ(buffer[i], static_cast<byte>(verify_idx)); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 656 | } |
| 657 | } |
| 658 | } |
| 659 | } |
| 660 | } |
| 661 | |
Wyatt Hepler | 595cf01 | 2020-02-05 09:31:02 -0800 | [diff] [blame] | 662 | TEST_F(KeyValueStoreTest, Enable) { |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 663 | KvsAttributes kvs_attr(std::strlen(keys[0]), buffer.size()); |
| 664 | |
| 665 | // Verify the data will fit in this test partition. This checks that all the |
| 666 | // keys chunks will fit and a header for each sector will fit. It requires 1 |
| 667 | // empty sector also. |
| 668 | const size_t kAllChunkSize = kvs_attr.MinPutSize() * keys.size(); |
| 669 | const size_t kAllSectorHeaderSizes = |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 670 | kvs_attr.SectorHeaderSize() * (test_partition.sector_count() - 1); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 671 | const size_t kMinSize = kAllChunkSize + kAllSectorHeaderSizes; |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 672 | const size_t kAvailSectorSpace = |
| 673 | test_partition.sector_size_bytes() * (test_partition.sector_count() - 1); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 674 | if (kAvailSectorSpace < kMinSize) { |
Wyatt Hepler | 2ad6067 | 2020-01-21 08:00:16 -0800 | [diff] [blame] | 675 | PW_LOG_INFO("KVS too small, skipping test."); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 676 | return; |
| 677 | } |
| 678 | |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 679 | // Add some items |
| 680 | for (unsigned add_idx = 0; add_idx < keys.size(); add_idx++) { |
Wyatt Hepler | acaacf9 | 2020-01-24 10:58:30 -0800 | [diff] [blame] | 681 | std::memset(buffer.data(), add_idx, buffer.size()); |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 682 | ASSERT_EQ(Status::OK, kvs_.Put(keys[add_idx], buffer)); |
| 683 | EXPECT_EQ(kvs_.size(), add_idx + 1); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 684 | } |
| 685 | |
| 686 | // Enable different KVS which should be able to properly setup the same map |
| 687 | // from what is stored in flash. |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 688 | static KeyValueStore kvs_local(&test_partition, format); |
| 689 | ASSERT_EQ(Status::OK, kvs_local.Init()); |
| 690 | EXPECT_EQ(kvs_local.size(), keys.size()); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 691 | |
| 692 | // Ensure adding to new KVS works |
| 693 | uint8_t value = 0xDA; |
| 694 | const char* key = "new_key"; |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 695 | ASSERT_EQ(Status::OK, kvs_local.Put(key, value)); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 696 | uint8_t test; |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 697 | ASSERT_EQ(Status::OK, kvs_local.Get(key, &test)); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 698 | EXPECT_EQ(value, test); |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 699 | EXPECT_EQ(kvs_local.size(), keys.size() + 1); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 700 | |
| 701 | // Verify previous data |
| 702 | for (unsigned verify_idx = 0; verify_idx < keys.size(); verify_idx++) { |
Wyatt Hepler | acaacf9 | 2020-01-24 10:58:30 -0800 | [diff] [blame] | 703 | std::memset(buffer.data(), 0, buffer.size()); |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 704 | ASSERT_EQ(Status::OK, kvs_local.Get(keys[verify_idx], buffer).status()); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 705 | for (uint32_t i = 0; i < buffer.size(); i++) { |
Wyatt Hepler | acaacf9 | 2020-01-24 10:58:30 -0800 | [diff] [blame] | 706 | EXPECT_EQ(static_cast<unsigned>(buffer[i]), verify_idx); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 707 | } |
| 708 | } |
| 709 | } |
| 710 | |
Wyatt Hepler | 6c24c06 | 2020-02-05 15:30:49 -0800 | [diff] [blame^] | 711 | TEST_F(KeyValueStoreTest, MultiSector) { |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 712 | // Calculate number of elements to ensure multiple sectors are required. |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 713 | uint16_t add_count = (test_partition.sector_size_bytes() / buffer.size()) + 1; |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 714 | |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 715 | if (kvs_.max_size() < add_count) { |
Wyatt Hepler | 2ad6067 | 2020-01-21 08:00:16 -0800 | [diff] [blame] | 716 | PW_LOG_INFO("Sector size too large, skipping test."); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 717 | return; // this chip has very large sectors, test won't work |
| 718 | } |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 719 | if (test_partition.sector_count() < 3) { |
Wyatt Hepler | 2ad6067 | 2020-01-21 08:00:16 -0800 | [diff] [blame] | 720 | PW_LOG_INFO("Not enough sectors, skipping test."); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 721 | return; // need at least 3 sectors for multi-sector test |
| 722 | } |
| 723 | |
| 724 | char key[20]; |
| 725 | for (unsigned add_idx = 0; add_idx < add_count; add_idx++) { |
Wyatt Hepler | acaacf9 | 2020-01-24 10:58:30 -0800 | [diff] [blame] | 726 | std::memset(buffer.data(), add_idx, buffer.size()); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 727 | snprintf(key, sizeof(key), "key_%u", add_idx); |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 728 | ASSERT_EQ(Status::OK, kvs_.Put(key, buffer)); |
| 729 | EXPECT_EQ(kvs_.size(), add_idx + 1); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 730 | } |
| 731 | |
| 732 | for (unsigned verify_idx = 0; verify_idx < add_count; verify_idx++) { |
Wyatt Hepler | acaacf9 | 2020-01-24 10:58:30 -0800 | [diff] [blame] | 733 | std::memset(buffer.data(), 0, buffer.size()); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 734 | snprintf(key, sizeof(key), "key_%u", verify_idx); |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 735 | ASSERT_EQ(Status::OK, kvs_.Get(key, buffer).status()); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 736 | for (uint32_t i = 0; i < buffer.size(); i++) { |
Wyatt Hepler | acaacf9 | 2020-01-24 10:58:30 -0800 | [diff] [blame] | 737 | EXPECT_EQ(static_cast<unsigned>(buffer[i]), verify_idx); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 738 | } |
| 739 | } |
| 740 | |
| 741 | // Check erase |
| 742 | for (unsigned erase_idx = 0; erase_idx < add_count; erase_idx++) { |
| 743 | snprintf(key, sizeof(key), "key_%u", erase_idx); |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 744 | ASSERT_EQ(Status::OK, kvs_.Delete(key)); |
| 745 | EXPECT_EQ(kvs_.size(), add_count - erase_idx - 1); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 746 | } |
| 747 | } |
| 748 | |
Wyatt Hepler | 595cf01 | 2020-02-05 09:31:02 -0800 | [diff] [blame] | 749 | TEST_F(KeyValueStoreTest, RewriteValue) { |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 750 | // Write first value |
| 751 | const uint8_t kValue1 = 0xDA; |
| 752 | const uint8_t kValue2 = 0x12; |
| 753 | const char* key = "the_key"; |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 754 | ASSERT_EQ(Status::OK, kvs_.Put(key, as_bytes(span(&kValue1, 1)))); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 755 | |
| 756 | // Verify |
| 757 | uint8_t value; |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 758 | ASSERT_EQ(Status::OK, |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 759 | kvs_.Get(key, as_writable_bytes(span(&value, 1))).status()); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 760 | EXPECT_EQ(kValue1, value); |
| 761 | |
| 762 | // Write new value for key |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 763 | ASSERT_EQ(Status::OK, kvs_.Put(key, as_bytes(span(&kValue2, 1)))); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 764 | |
| 765 | // Verify |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 766 | ASSERT_EQ(Status::OK, |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 767 | kvs_.Get(key, as_writable_bytes(span(&value, 1))).status()); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 768 | EXPECT_EQ(kValue2, value); |
| 769 | |
| 770 | // Verify only 1 element exists |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 771 | EXPECT_EQ(kvs_.size(), 1u); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 772 | } |
| 773 | |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 774 | #if 0 // Offset reads are not yet supported |
| 775 | |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 776 | TEST_F(KeyValueStoreTest, OffsetRead) { |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 777 | const char* key = "the_key"; |
Wyatt Hepler | acaacf9 | 2020-01-24 10:58:30 -0800 | [diff] [blame] | 778 | constexpr size_t kReadSize = 16; // needs to be a multiple of alignment |
| 779 | constexpr size_t kTestBufferSize = kReadSize * 10; |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 780 | ASSERT_GT(buffer.size(), kTestBufferSize); |
| 781 | ASSERT_LE(kTestBufferSize, 0xFF); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 782 | |
| 783 | // Write the entire buffer |
Wyatt Hepler | acaacf9 | 2020-01-24 10:58:30 -0800 | [diff] [blame] | 784 | for (size_t i = 0; i < kTestBufferSize; i++) { |
| 785 | buffer[i] = byte(i); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 786 | } |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 787 | ASSERT_EQ(Status::OK, kvs_.Put(key, span(buffer.data(), kTestBufferSize))); |
| 788 | EXPECT_EQ(kvs_.size(), 1u); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 789 | |
| 790 | // Read in small chunks and verify |
Wyatt Hepler | acaacf9 | 2020-01-24 10:58:30 -0800 | [diff] [blame] | 791 | for (unsigned i = 0; i < kTestBufferSize / kReadSize; i++) { |
| 792 | std::memset(buffer.data(), 0, buffer.size()); |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 793 | ASSERT_EQ( |
| 794 | Status::OK, |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 795 | kvs_.Get(key, span(buffer.data(), kReadSize), i * kReadSize).status()); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 796 | for (unsigned j = 0; j < kReadSize; j++) { |
Wyatt Hepler | acaacf9 | 2020-01-24 10:58:30 -0800 | [diff] [blame] | 797 | ASSERT_EQ(static_cast<unsigned>(buffer[j]), j + i * kReadSize); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 798 | } |
| 799 | } |
| 800 | } |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 801 | #endif |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 802 | |
Wyatt Hepler | 595cf01 | 2020-02-05 09:31:02 -0800 | [diff] [blame] | 803 | TEST_F(KeyValueStoreTest, MultipleRewrite) { |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 804 | // Calculate number of elements to ensure multiple sectors are required. |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 805 | unsigned add_count = (test_partition.sector_size_bytes() / buffer.size()) + 1; |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 806 | |
| 807 | const char* key = "the_key"; |
| 808 | constexpr uint8_t kGoodVal = 0x60; |
| 809 | constexpr uint8_t kBadVal = 0xBA; |
Wyatt Hepler | acaacf9 | 2020-01-24 10:58:30 -0800 | [diff] [blame] | 810 | std::memset(buffer.data(), kBadVal, buffer.size()); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 811 | for (unsigned add_idx = 0; add_idx < add_count; add_idx++) { |
| 812 | if (add_idx == add_count - 1) { // last value |
Wyatt Hepler | acaacf9 | 2020-01-24 10:58:30 -0800 | [diff] [blame] | 813 | std::memset(buffer.data(), kGoodVal, buffer.size()); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 814 | } |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 815 | ASSERT_EQ(Status::OK, kvs_.Put(key, buffer)); |
| 816 | EXPECT_EQ(kvs_.size(), 1u); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 817 | } |
| 818 | |
| 819 | // Verify |
Wyatt Hepler | acaacf9 | 2020-01-24 10:58:30 -0800 | [diff] [blame] | 820 | std::memset(buffer.data(), 0, buffer.size()); |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 821 | ASSERT_EQ(Status::OK, kvs_.Get(key, buffer).status()); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 822 | for (uint32_t i = 0; i < buffer.size(); i++) { |
Wyatt Hepler | acaacf9 | 2020-01-24 10:58:30 -0800 | [diff] [blame] | 823 | ASSERT_EQ(buffer[i], static_cast<byte>(kGoodVal)); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 824 | } |
| 825 | } |
| 826 | |
Wyatt Hepler | 6c24c06 | 2020-02-05 15:30:49 -0800 | [diff] [blame^] | 827 | TEST_F(KeyValueStoreTest, FillSector) { |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 828 | ASSERT_EQ(std::strlen(keys[0]), 8U); // Easier for alignment |
| 829 | ASSERT_EQ(std::strlen(keys[2]), 8U); // Easier for alignment |
| 830 | constexpr size_t kTestDataSize = 8; |
| 831 | KvsAttributes kvs_attr(std::strlen(keys[2]), kTestDataSize); |
| 832 | int bytes_remaining = |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 833 | test_partition.sector_size_bytes() - kvs_attr.SectorHeaderSize(); |
Wyatt Hepler | acaacf9 | 2020-01-24 10:58:30 -0800 | [diff] [blame] | 834 | constexpr byte kKey0Pattern = byte{0xBA}; |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 835 | |
Wyatt Hepler | acaacf9 | 2020-01-24 10:58:30 -0800 | [diff] [blame] | 836 | std::memset( |
| 837 | buffer.data(), static_cast<int>(kKey0Pattern), kvs_attr.DataSize()); |
| 838 | ASSERT_EQ(Status::OK, |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 839 | kvs_.Put(keys[0], span(buffer.data(), kvs_attr.DataSize()))); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 840 | bytes_remaining -= kvs_attr.MinPutSize(); |
Wyatt Hepler | acaacf9 | 2020-01-24 10:58:30 -0800 | [diff] [blame] | 841 | std::memset(buffer.data(), 1, kvs_attr.DataSize()); |
| 842 | ASSERT_EQ(Status::OK, |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 843 | kvs_.Put(keys[2], span(buffer.data(), kvs_attr.DataSize()))); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 844 | bytes_remaining -= kvs_attr.MinPutSize(); |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 845 | EXPECT_EQ(kvs_.size(), 2u); |
| 846 | ASSERT_EQ(Status::OK, kvs_.Delete(keys[2])); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 847 | bytes_remaining -= kvs_attr.EraseSize(); |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 848 | EXPECT_EQ(kvs_.size(), 1u); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 849 | |
| 850 | // Intentionally adding erase size to trigger sector cleanup |
| 851 | bytes_remaining += kvs_attr.EraseSize(); |
| 852 | FillKvs(keys[2], bytes_remaining); |
| 853 | |
| 854 | // Verify key[0] |
Wyatt Hepler | acaacf9 | 2020-01-24 10:58:30 -0800 | [diff] [blame] | 855 | std::memset(buffer.data(), 0, kvs_attr.DataSize()); |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 856 | ASSERT_EQ( |
| 857 | Status::OK, |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 858 | kvs_.Get(keys[0], span(buffer.data(), kvs_attr.DataSize())).status()); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 859 | for (uint32_t i = 0; i < kvs_attr.DataSize(); i++) { |
| 860 | EXPECT_EQ(buffer[i], kKey0Pattern); |
| 861 | } |
| 862 | } |
| 863 | |
Wyatt Hepler | 6c24c06 | 2020-02-05 15:30:49 -0800 | [diff] [blame^] | 864 | TEST_F(KeyValueStoreTest, Interleaved) { |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 865 | const uint8_t kValue1 = 0xDA; |
| 866 | const uint8_t kValue2 = 0x12; |
Wyatt Hepler | acaacf9 | 2020-01-24 10:58:30 -0800 | [diff] [blame] | 867 | uint8_t value; |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 868 | ASSERT_EQ(Status::OK, kvs_.Put(keys[0], kValue1)); |
| 869 | EXPECT_EQ(kvs_.size(), 1u); |
| 870 | ASSERT_EQ(Status::OK, kvs_.Delete(keys[0])); |
| 871 | EXPECT_EQ(kvs_.Get(keys[0], &value), Status::NOT_FOUND); |
| 872 | ASSERT_EQ(Status::OK, kvs_.Put(keys[1], as_bytes(span(&kValue1, 1)))); |
| 873 | ASSERT_EQ(Status::OK, kvs_.Put(keys[2], kValue2)); |
| 874 | ASSERT_EQ(Status::OK, kvs_.Delete(keys[1])); |
| 875 | EXPECT_EQ(Status::OK, kvs_.Get(keys[2], &value)); |
Wyatt Hepler | acaacf9 | 2020-01-24 10:58:30 -0800 | [diff] [blame] | 876 | EXPECT_EQ(kValue2, value); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 877 | |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 878 | EXPECT_EQ(kvs_.size(), 1u); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 879 | } |
| 880 | |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 881 | TEST_F(KeyValueStoreTest, DISABLED_BadCrc) { |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 882 | static constexpr uint32_t kTestPattern = 0xBAD0301f; |
| 883 | // clang-format off |
| 884 | // There is a top and bottom because for each because we don't want to write |
| 885 | // the erase 0xFF, especially on encrypted flash. |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 886 | static constexpr auto kKvsTestDataAligned1Top = ByteArray( |
| 887 | 0xCD, 0xAB, 0x03, 0x00, 0x01, 0x00, 0xFF, 0xFF // Sector Header |
| 888 | ); |
| 889 | static constexpr auto kKvsTestDataAligned1Bottom = ByteArray( |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 890 | 0xAA, 0x55, 0xBA, 0xDD, 0x00, 0x00, 0x18, 0x00, // header (BAD CRC) |
| 891 | 0x54, 0x65, 0x73, 0x74, 0x4B, 0x65, 0x79, 0x31, // Key (keys[0]) |
| 892 | 0xDA, // Value |
| 893 | 0xAA, 0x55, 0xB5, 0x87, 0x00, 0x00, 0x44, 0x00, // Header (GOOD CRC) |
| 894 | 0x4B, 0x65, 0x79, 0x32, // Key (keys[1]) |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 895 | 0x1F, 0x30, 0xD0, 0xBA); // Value |
| 896 | static constexpr auto kKvsTestDataAligned2Top = ByteArray( |
| 897 | 0xCD, 0xAB, 0x03, 0x00, 0x02, 0x00, 0xFF, 0xFF // Sector Header |
| 898 | ); |
| 899 | static constexpr auto kKvsTestDataAligned2Bottom = ByteArray( |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 900 | 0xAA, 0x55, 0xBA, 0xDD, 0x00, 0x00, 0x18, 0x00, // header (BAD CRC) |
| 901 | 0x54, 0x65, 0x73, 0x74, 0x4B, 0x65, 0x79, 0x31, // Key (keys[0]) |
| 902 | 0xDA, 0x00, // Value + padding |
| 903 | 0xAA, 0x55, 0xB5, 0x87, 0x00, 0x00, 0x44, 0x00, // Header (GOOD CRC) |
| 904 | 0x4B, 0x65, 0x79, 0x32, // Key (keys[1]) |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 905 | 0x1F, 0x30, 0xD0, 0xBA // Value |
Keir Mierle | 8c352dc | 2020-02-02 13:58:19 -0800 | [diff] [blame] | 906 | ); |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 907 | static constexpr auto kKvsTestDataAligned8Top = ByteArray( |
| 908 | 0xCD, 0xAB, 0x03, 0x00, 0x08, 0x00, 0xFF, 0xFF // Sector Header |
| 909 | ); |
| 910 | static constexpr auto kKvsTestDataAligned8Bottom = ByteArray( |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 911 | 0xAA, 0x55, 0xBA, 0xDD, 0x00, 0x00, 0x18, 0x00, // header (BAD CRC) |
| 912 | 0x54, 0x65, 0x73, 0x74, 0x4B, 0x65, 0x79, 0x31, // Key (keys[0]) |
| 913 | 0xDA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Value + padding |
| 914 | 0xAA, 0x55, 0xB5, 0x87, 0x00, 0x00, 0x44, 0x00, // header (GOOD CRC) |
| 915 | 0x4B, 0x65, 0x79, 0x32, 0x00, 0x00, 0x00, 0x00, // Key (keys[1]) |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 916 | 0x1F, 0x30, 0xD0, 0xBA, 0x00, 0x00, 0x00, 0x00 // Value + padding |
| 917 | ); |
| 918 | static constexpr auto kKvsTestDataAligned16Top = ByteArray( |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 919 | 0xCD, 0xAB, 0x03, 0x00, 0x10, 0x00, 0xFF, 0xFF, // Sector Header |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 920 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // Alignment to 16 |
| 921 | ); |
| 922 | static constexpr auto kKvsTestDataAligned16Bottom = ByteArray( |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 923 | 0xAA, 0x55, 0xBA, 0xDD, 0x00, 0x00, 0x18, 0x00, // header (BAD CRC) |
| 924 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Alignment to 16 |
| 925 | 0x54, 0x65, 0x73, 0x74, 0x4B, 0x65, 0x79, 0x31, // Key (keys[0]) |
| 926 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Alignment to 16 |
| 927 | 0xDA, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Value + padding |
| 928 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Alignment to 16 |
| 929 | 0xAA, 0x55, 0xB5, 0x87, 0x00, 0x00, 0x44, 0x00, // header (GOOD CRC) |
| 930 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Alignment to 16 |
| 931 | 0x4B, 0x65, 0x79, 0x32, 0x00, 0x00, 0x00, 0x00, // Key (keys[1]) |
| 932 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Alignment to 16 |
| 933 | 0x1F, 0x30, 0xD0, 0xBA, 0x00, 0x00, 0x00, 0x00, // Value + padding |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 934 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // Alignment to 16 |
| 935 | ); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 936 | // clang-format on |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 937 | |
| 938 | // We don't actually care about the size values provided, since we are only |
| 939 | // using kvs_attr to get Sector Size |
| 940 | KvsAttributes kvs_attr(8, 8); |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 941 | if (test_partition.alignment_bytes() == 1) { |
Wyatt Hepler | 2ad6067 | 2020-01-21 08:00:16 -0800 | [diff] [blame] | 942 | ASSERT_EQ(Status::OK, |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 943 | test_partition.Write(0, kKvsTestDataAligned1Top).status()); |
Wyatt Hepler | 2ad6067 | 2020-01-21 08:00:16 -0800 | [diff] [blame] | 944 | ASSERT_EQ( |
| 945 | Status::OK, |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 946 | test_partition |
| 947 | .Write(kvs_attr.SectorHeaderSize(), kKvsTestDataAligned1Bottom) |
| 948 | .status()); |
| 949 | } else if (test_partition.alignment_bytes() == 2) { |
Wyatt Hepler | 2ad6067 | 2020-01-21 08:00:16 -0800 | [diff] [blame] | 950 | ASSERT_EQ(Status::OK, |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 951 | test_partition.Write(0, kKvsTestDataAligned2Top).status()); |
| 952 | ASSERT_EQ( |
| 953 | Status::OK, |
| 954 | test_partition |
| 955 | .Write(kvs_attr.SectorHeaderSize(), kKvsTestDataAligned2Bottom) |
| 956 | .status()); |
| 957 | } else if (test_partition.alignment_bytes() == 8) { |
| 958 | ASSERT_EQ(Status::OK, |
| 959 | test_partition.Write(0, kKvsTestDataAligned8Top).status()); |
| 960 | ASSERT_EQ( |
| 961 | Status::OK, |
| 962 | test_partition |
| 963 | .Write(kvs_attr.SectorHeaderSize(), kKvsTestDataAligned8Bottom) |
| 964 | .status()); |
| 965 | } else if (test_partition.alignment_bytes() == 16) { |
| 966 | ASSERT_EQ(Status::OK, |
| 967 | test_partition.Write(0, kKvsTestDataAligned16Top).status()); |
| 968 | ASSERT_EQ( |
| 969 | Status::OK, |
| 970 | test_partition |
| 971 | .Write(kvs_attr.SectorHeaderSize(), kKvsTestDataAligned16Bottom) |
| 972 | .status()); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 973 | } else { |
Wyatt Hepler | 2ad6067 | 2020-01-21 08:00:16 -0800 | [diff] [blame] | 974 | PW_LOG_ERROR("Test only supports 1, 2, 8 and 16 byte alignments."); |
| 975 | ASSERT_EQ(Status::OK, false); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 976 | } |
| 977 | |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 978 | EXPECT_EQ(Status::DATA_LOSS, |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 979 | kvs_.Get(keys[0], span(buffer.data(), 1)).status()); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 980 | |
| 981 | // Value with correct CRC should still be available. |
| 982 | uint32_t test2 = 0; |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 983 | ASSERT_EQ(Status::OK, kvs_.Get(keys[1], &test2)); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 984 | EXPECT_EQ(kTestPattern, test2); |
| 985 | |
| 986 | // Test rewriting over corrupted data. |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 987 | ASSERT_EQ(Status::OK, kvs_.Put(keys[0], kTestPattern)); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 988 | test2 = 0; |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 989 | EXPECT_EQ(Status::OK, kvs_.Get(keys[0], &test2)); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 990 | EXPECT_EQ(kTestPattern, test2); |
| 991 | |
| 992 | // Check correct when re-enabled |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 993 | EXPECT_EQ(kvs_.Init(), Status::OK); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 994 | test2 = 0; |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 995 | EXPECT_EQ(Status::OK, kvs_.Get(keys[0], &test2)); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 996 | EXPECT_EQ(kTestPattern, test2); |
| 997 | } |
| 998 | |
Wyatt Hepler | 595cf01 | 2020-02-05 09:31:02 -0800 | [diff] [blame] | 999 | TEST_F(KeyValueStoreTest, TestVersion2) { |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1000 | static constexpr uint32_t kTestPattern = 0xBAD0301f; |
| 1001 | // Since this test is not run on encypted flash, we can write the clean |
| 1002 | // pending flag for just this test. |
| 1003 | static constexpr uint8_t kKvsTestDataAligned1[] = { |
| 1004 | 0xCD, 0xAB, 0x02, 0x00, 0x00, 0x00, 0xFF, 0xFF, // Sector Header |
| 1005 | 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, // Clean pending flag |
| 1006 | 0xAA, 0x55, 0xB5, 0x87, 0x00, 0x00, 0x44, 0x00, // Header (GOOD CRC) |
| 1007 | 0x4B, 0x65, 0x79, 0x32, // Key (keys[1]) |
| 1008 | 0x1F, 0x30, 0xD0, 0xBA}; // Value |
| 1009 | |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 1010 | if (test_partition.alignment_bytes() == 1) { |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1011 | // Test only runs on 1 byte alignment partitions |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 1012 | test_partition.Erase(0, test_partition.sector_count()); |
| 1013 | test_partition.Write(0, as_bytes(span(kKvsTestDataAligned1))); |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 1014 | EXPECT_EQ(Status::OK, kvs_.Init()); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1015 | uint32_t test2 = 0; |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 1016 | ASSERT_EQ(Status::OK, |
| 1017 | kvs_.Get(keys[1], as_writable_bytes(span(&test2, 1))).status()); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1018 | EXPECT_EQ(kTestPattern, test2); |
| 1019 | } |
| 1020 | } |
| 1021 | |
Wyatt Hepler | 6c24c06 | 2020-02-05 15:30:49 -0800 | [diff] [blame^] | 1022 | TEST_F(KeyValueStoreTest, DeleteAndReinitialize) { |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1023 | // Write value |
| 1024 | const uint8_t kValue = 0xDA; |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 1025 | ASSERT_EQ(Status::OK, kvs_.Put(keys[0], kValue)); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1026 | |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 1027 | ASSERT_EQ(Status::OK, kvs_.Delete(keys[0])); |
Wyatt Hepler | acaacf9 | 2020-01-24 10:58:30 -0800 | [diff] [blame] | 1028 | uint8_t value; |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 1029 | ASSERT_EQ(kvs_.Get(keys[0], &value), Status::NOT_FOUND); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1030 | |
| 1031 | // Reset KVS, ensure captured at enable |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 1032 | ASSERT_EQ(Status::OK, kvs_.Init()); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1033 | |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 1034 | ASSERT_EQ(kvs_.Get(keys[0], &value), Status::NOT_FOUND); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1035 | } |
| 1036 | |
Wyatt Hepler | 595cf01 | 2020-02-05 09:31:02 -0800 | [diff] [blame] | 1037 | TEST_F(KeyValueStoreTest, TemplatedPutAndGet) { |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1038 | // Store a value with the convenience method. |
| 1039 | const uint32_t kValue = 0x12345678; |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 1040 | ASSERT_EQ(Status::OK, kvs_.Put(keys[0], kValue)); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1041 | |
| 1042 | // Read it back with the other convenience method. |
| 1043 | uint32_t value; |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 1044 | ASSERT_EQ(Status::OK, kvs_.Get(keys[0], &value)); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1045 | ASSERT_EQ(kValue, value); |
| 1046 | |
| 1047 | // Make sure we cannot get something where size isn't what we expect |
| 1048 | const uint8_t kSmallValue = 0xBA; |
| 1049 | uint8_t small_value = kSmallValue; |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 1050 | ASSERT_EQ(kvs_.Get(keys[0], &small_value), Status::INVALID_ARGUMENT); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1051 | ASSERT_EQ(small_value, kSmallValue); |
| 1052 | } |
| 1053 | |
Wyatt Hepler | 6c24c06 | 2020-02-05 15:30:49 -0800 | [diff] [blame^] | 1054 | TEST_F(KeyValueStoreTest, Delete) { |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1055 | static constexpr uint32_t kTestPattern = 0xBAD0301f; |
| 1056 | // clang-format off |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 1057 | static constexpr auto kKvsTestDataAligned1Top = ByteArray( |
| 1058 | 0xCD, 0xAB, 0x02, 0x00, 0x00, 0x00, 0xFF, 0xFF // Sector Header |
| 1059 | ); |
| 1060 | static constexpr auto kKvsTestDataAligned1Bottom = ByteArray( |
| 1061 | 0xAA, 0x55, 0xB5, 0x87, 0x00, 0x00, 0x44, 0x00, // Header (GOOD CRC) |
| 1062 | 0x4B, 0x65, 0x79, 0x32, // Key (keys[1]) |
| 1063 | 0x1F, 0x30, 0xD0, 0xBA // Value |
| 1064 | ); |
| 1065 | static constexpr auto kKvsTestDataAligned2Top = ByteArray( |
| 1066 | 0xCD, 0xAB, 0x03, 0x00, 0x02, 0x00, 0xFF, 0xFF // Sector Header |
| 1067 | ); |
| 1068 | static constexpr auto kKvsTestDataAligned2Bottom = ByteArray( |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1069 | 0xAA, 0x55, 0xB5, 0x87, 0x00, 0x00, 0x44, 0x00, // Header (GOOD CRC) |
| 1070 | 0x4B, 0x65, 0x79, 0x32, // Key (keys[1]) |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 1071 | 0x1F, 0x30, 0xD0, 0xBA // Value |
| 1072 | ); |
| 1073 | static constexpr auto kKvsTestDataAligned8Top = ByteArray( |
| 1074 | 0xCD, 0xAB, 0x03, 0x00, 0x08, 0x00, 0xFF, 0xFF // Sector Header |
| 1075 | ); |
| 1076 | static constexpr auto kKvsTestDataAligned8Bottom = ByteArray( |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1077 | 0xAA, 0x55, 0xB5, 0x87, 0x00, 0x00, 0x44, 0x00, // header (GOOD CRC) |
| 1078 | 0x4B, 0x65, 0x79, 0x32, 0x00, 0x00, 0x00, 0x00, // Key (keys[1]) |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 1079 | 0x1F, 0x30, 0xD0, 0xBA, 0x00, 0x00, 0x00, 0x00 // Value + padding |
| 1080 | ); |
| 1081 | static constexpr auto kKvsTestDataAligned16Top = ByteArray( |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1082 | 0xCD, 0xAB, 0x03, 0x00, 0x10, 0x00, 0xFF, 0xFF, // Sector Header |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 1083 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // Alignment to 16 |
| 1084 | ); |
| 1085 | static constexpr auto kKvsTestDataAligned16Bottom = ByteArray( |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1086 | 0xAA, 0x55, 0xB5, 0x87, 0x00, 0x00, 0x44, 0x00, // header (GOOD CRC) |
| 1087 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Alignment to 16 |
| 1088 | 0x4B, 0x65, 0x79, 0x32, 0x00, 0x00, 0x00, 0x00, // Key (keys[1]) |
| 1089 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Alignment to 16 |
| 1090 | 0x1F, 0x30, 0xD0, 0xBA, 0x00, 0x00, 0x00, 0x00, // Value + padding |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 1091 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // Alignment to 16 |
| 1092 | ); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1093 | // clang-format on |
| 1094 | |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 1095 | ASSERT_EQ(Status::OK, test_partition.Erase(0, test_partition.sector_count())); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1096 | // We don't actually care about the size values provided, since we are only |
| 1097 | // using kvs_attr to get Sector Size |
| 1098 | KvsAttributes kvs_attr(8, 8); |
Wyatt Hepler | 2ad6067 | 2020-01-21 08:00:16 -0800 | [diff] [blame] | 1099 | FlashPartition::Address address = kvs_attr.SectorHeaderSize(); |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 1100 | if (test_partition.alignment_bytes() == 1) { |
Wyatt Hepler | 2ad6067 | 2020-01-21 08:00:16 -0800 | [diff] [blame] | 1101 | ASSERT_EQ(Status::OK, |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 1102 | test_partition.Write(0, kKvsTestDataAligned1Top).status()); |
Wyatt Hepler | 2ad6067 | 2020-01-21 08:00:16 -0800 | [diff] [blame] | 1103 | ASSERT_EQ( |
| 1104 | Status::OK, |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 1105 | test_partition.Write(address, kKvsTestDataAligned1Bottom).status()); |
| 1106 | address += sizeof(kKvsTestDataAligned1Bottom); |
| 1107 | } else if (test_partition.alignment_bytes() == 2) { |
Wyatt Hepler | 2ad6067 | 2020-01-21 08:00:16 -0800 | [diff] [blame] | 1108 | ASSERT_EQ(Status::OK, |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 1109 | test_partition.Write(0, kKvsTestDataAligned2Top).status()); |
| 1110 | ASSERT_EQ( |
| 1111 | Status::OK, |
| 1112 | test_partition.Write(address, kKvsTestDataAligned2Bottom).status()); |
| 1113 | address += sizeof(kKvsTestDataAligned2Bottom); |
| 1114 | } else if (test_partition.alignment_bytes() == 8) { |
| 1115 | ASSERT_EQ(Status::OK, |
| 1116 | test_partition.Write(0, kKvsTestDataAligned8Top).status()); |
| 1117 | ASSERT_EQ( |
| 1118 | Status::OK, |
| 1119 | test_partition.Write(address, kKvsTestDataAligned8Bottom).status()); |
| 1120 | address += sizeof(kKvsTestDataAligned8Bottom); |
| 1121 | } else if (test_partition.alignment_bytes() == 16) { |
| 1122 | ASSERT_EQ(Status::OK, |
| 1123 | test_partition.Write(0, kKvsTestDataAligned16Top).status()); |
| 1124 | ASSERT_EQ( |
| 1125 | Status::OK, |
| 1126 | test_partition.Write(address, kKvsTestDataAligned16Bottom).status()); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1127 | address += sizeof(kKvsTestDataAligned16Bottom); |
| 1128 | } else { |
Wyatt Hepler | 2ad6067 | 2020-01-21 08:00:16 -0800 | [diff] [blame] | 1129 | PW_LOG_ERROR("Test only supports 1, 2, 8 and 16 byte alignments."); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1130 | ASSERT_EQ(true, false); |
| 1131 | } |
| 1132 | |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1133 | // Put in same key/value pair |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 1134 | ASSERT_EQ(Status::OK, kvs_.Put(keys[1], kTestPattern)); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1135 | |
| 1136 | bool is_erased = false; |
Wyatt Hepler | 2ad6067 | 2020-01-21 08:00:16 -0800 | [diff] [blame] | 1137 | ASSERT_EQ(Status::OK, |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 1138 | test_partition.IsRegionErased( |
| 1139 | address, test_partition.alignment_bytes(), &is_erased)); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1140 | EXPECT_EQ(is_erased, true); |
| 1141 | } |
| 1142 | |
| 1143 | // This test is derived from bug that was discovered. Testing this corner case |
| 1144 | // relies on creating a new key-value just under the size that is left over in |
| 1145 | // the sector. |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 1146 | TEST_F(KeyValueStoreTest, DISABLED_FillSector2) { |
| 1147 | if (test_partition.sector_count() < 3) { |
Wyatt Hepler | 2ad6067 | 2020-01-21 08:00:16 -0800 | [diff] [blame] | 1148 | PW_LOG_INFO("Not enough sectors, skipping test."); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1149 | return; // need at least 3 sectors |
| 1150 | } |
| 1151 | |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1152 | // Start of by filling flash sector to near full |
| 1153 | constexpr int kHalfBufferSize = buffer.size() / 2; |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 1154 | const int kSizeToFill = test_partition.sector_size_bytes() - kHalfBufferSize; |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1155 | constexpr size_t kTestDataSize = 8; |
| 1156 | KvsAttributes kvs_attr(std::strlen(keys[2]), kTestDataSize); |
| 1157 | |
| 1158 | FillKvs(keys[2], kSizeToFill); |
| 1159 | |
| 1160 | // Find out how much space is remaining for new key-value and confirm it |
| 1161 | // makes sense. |
| 1162 | size_t new_keyvalue_size = 0; |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 1163 | size_t alignment = test_partition.alignment_bytes(); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1164 | // Starts on second sector since it will try to keep first sector free |
Wyatt Hepler | 2ad6067 | 2020-01-21 08:00:16 -0800 | [diff] [blame] | 1165 | FlashPartition::Address read_address = |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 1166 | 2 * test_partition.sector_size_bytes() - alignment; |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1167 | for (; read_address > 0; read_address -= alignment) { |
| 1168 | bool is_erased = false; |
Wyatt Hepler | 2ad6067 | 2020-01-21 08:00:16 -0800 | [diff] [blame] | 1169 | ASSERT_EQ( |
| 1170 | Status::OK, |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 1171 | test_partition.IsRegionErased(read_address, alignment, &is_erased)); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1172 | if (is_erased) { |
| 1173 | new_keyvalue_size += alignment; |
| 1174 | } else { |
| 1175 | break; |
| 1176 | } |
| 1177 | } |
| 1178 | |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 1179 | size_t expected_remaining = test_partition.sector_size_bytes() - |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1180 | kvs_attr.SectorHeaderSize() - kSizeToFill; |
| 1181 | ASSERT_EQ(new_keyvalue_size, expected_remaining); |
| 1182 | |
| 1183 | const char* kNewKey = "NewKey"; |
| 1184 | constexpr size_t kValueLessThanChunkHeaderSize = 2; |
Wyatt Hepler | acaacf9 | 2020-01-24 10:58:30 -0800 | [diff] [blame] | 1185 | constexpr auto kTestPattern = byte{0xBA}; |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1186 | new_keyvalue_size -= kValueLessThanChunkHeaderSize; |
Wyatt Hepler | acaacf9 | 2020-01-24 10:58:30 -0800 | [diff] [blame] | 1187 | std::memset(buffer.data(), static_cast<int>(kTestPattern), new_keyvalue_size); |
| 1188 | ASSERT_EQ(Status::OK, |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 1189 | kvs_.Put(kNewKey, span(buffer.data(), new_keyvalue_size))); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1190 | |
| 1191 | // In failed corner case, adding new key is deceptively successful. It isn't |
| 1192 | // until KVS is disabled and reenabled that issue can be detected. |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 1193 | ASSERT_EQ(Status::OK, kvs_.Init()); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1194 | |
| 1195 | // Might as well check that new key-value is what we expect it to be |
Wyatt Hepler | acaacf9 | 2020-01-24 10:58:30 -0800 | [diff] [blame] | 1196 | ASSERT_EQ(Status::OK, |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 1197 | kvs_.Get(kNewKey, span(buffer.data(), new_keyvalue_size)).status()); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1198 | for (size_t i = 0; i < new_keyvalue_size; i++) { |
| 1199 | EXPECT_EQ(buffer[i], kTestPattern); |
| 1200 | } |
| 1201 | } |
| 1202 | |
Wyatt Hepler | ed163b0 | 2020-02-03 17:49:32 -0800 | [diff] [blame] | 1203 | TEST_F(KeyValueStoreTest, ValueSize_Positive) { |
| 1204 | constexpr auto kData = ByteArray('h', 'i', '!'); |
| 1205 | ASSERT_EQ(Status::OK, kvs_.Put("TheKey", kData)); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1206 | |
Wyatt Hepler | ed163b0 | 2020-02-03 17:49:32 -0800 | [diff] [blame] | 1207 | auto result = kvs_.ValueSize("TheKey"); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1208 | |
Wyatt Hepler | ed163b0 | 2020-02-03 17:49:32 -0800 | [diff] [blame] | 1209 | EXPECT_EQ(Status::OK, result.status()); |
| 1210 | EXPECT_EQ(kData.size(), result.size()); |
| 1211 | } |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1212 | |
Wyatt Hepler | ed163b0 | 2020-02-03 17:49:32 -0800 | [diff] [blame] | 1213 | TEST_F(KeyValueStoreTest, ValueSize_Zero) { |
| 1214 | ASSERT_EQ(Status::OK, kvs_.Put("TheKey", as_bytes(span("123", 3)))); |
| 1215 | auto result = kvs_.ValueSize("TheKey"); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1216 | |
Wyatt Hepler | ed163b0 | 2020-02-03 17:49:32 -0800 | [diff] [blame] | 1217 | EXPECT_EQ(Status::OK, result.status()); |
| 1218 | EXPECT_EQ(3u, result.size()); |
| 1219 | } |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1220 | |
Wyatt Hepler | ed163b0 | 2020-02-03 17:49:32 -0800 | [diff] [blame] | 1221 | TEST_F(KeyValueStoreTest, ValueSize_InvalidKey) { |
| 1222 | EXPECT_EQ(Status::INVALID_ARGUMENT, kvs_.ValueSize("").status()); |
| 1223 | } |
| 1224 | |
| 1225 | TEST_F(KeyValueStoreTest, ValueSize_MissingKey) { |
| 1226 | EXPECT_EQ(Status::NOT_FOUND, kvs_.ValueSize("Not in there").status()); |
| 1227 | } |
| 1228 | |
Wyatt Hepler | 6c24c06 | 2020-02-05 15:30:49 -0800 | [diff] [blame^] | 1229 | TEST_F(KeyValueStoreTest, ValueSize_DeletedKey) { |
Wyatt Hepler | ed163b0 | 2020-02-03 17:49:32 -0800 | [diff] [blame] | 1230 | ASSERT_EQ(Status::OK, kvs_.Put("TheKey", as_bytes(span("123", 3)))); |
| 1231 | ASSERT_EQ(Status::OK, kvs_.Delete("TheKey")); |
| 1232 | |
| 1233 | EXPECT_EQ(Status::NOT_FOUND, kvs_.ValueSize("TheKey").status()); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1234 | } |
| 1235 | |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 1236 | #if 0 // TODO: not CanFitEntry function yet |
| 1237 | TEST_F(KeyValueStoreTest, DISABLED_CanFitEntryTests) { |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1238 | // Get exactly the number of bytes that can fit in the space remaining for |
| 1239 | // a large value, accounting for alignment. |
| 1240 | constexpr uint16_t kTestKeySize = 2; |
| 1241 | size_t space_remaining = |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 1242 | test_partition.sector_size_bytes() // |
| 1243 | - RoundUpForAlignment(sizeof(EntryHeader)) // TODO: Sector Header |
| 1244 | - RoundUpForAlignment(sizeof(EntryHeader)) // Cleaning Header |
| 1245 | - RoundUpForAlignment(sizeof(EntryHeader)) // TODO: Chunk Header |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1246 | - RoundUpForAlignment(kTestKeySize); |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 1247 | space_remaining -= test_partition.alignment_bytes() / 2; |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1248 | space_remaining = RoundUpForAlignment(space_remaining); |
| 1249 | |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 1250 | EXPECT_TRUE(kvs_.CanFitEntry(kTestKeySize, space_remaining)); |
| 1251 | EXPECT_FALSE(kvs_.CanFitEntry(kTestKeySize, space_remaining + 1)); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1252 | } |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 1253 | #endif |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1254 | |
Wyatt Hepler | 6e3a83b | 2020-02-04 07:36:45 -0800 | [diff] [blame] | 1255 | TEST_F(KeyValueStoreTest, DifferentValueSameCrc16) { |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1256 | const char kKey[] = "k"; |
| 1257 | // With the key and our CRC16 algorithm these both have CRC of 0x82AE |
| 1258 | // Given they are the same size and same key, the KVS will need to check |
| 1259 | // the actual bits to know they are different. |
| 1260 | const char kValue1[] = {'d', 'a', 't'}; |
| 1261 | const char kValue2[] = {'u', 'c', 'd'}; |
| 1262 | |
| 1263 | // Verify the CRC matches |
| 1264 | ASSERT_EQ(CalcKvsCrc(kKey, kValue1, sizeof(kValue1)), |
| 1265 | CalcKvsCrc(kKey, kValue2, sizeof(kValue2))); |
| 1266 | |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 1267 | ASSERT_EQ(Status::OK, kvs_.Put(kKey, kValue1)); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1268 | |
| 1269 | // Now try to rewrite with the similar value. |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 1270 | ASSERT_EQ(Status::OK, kvs_.Put(kKey, kValue2)); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1271 | |
| 1272 | // Read it back and check it is correct |
Wyatt Hepler | 6e3a83b | 2020-02-04 07:36:45 -0800 | [diff] [blame] | 1273 | char value[3] = {}; |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 1274 | ASSERT_EQ(Status::OK, kvs_.Get(kKey, &value)); |
Wyatt Hepler | acaacf9 | 2020-01-24 10:58:30 -0800 | [diff] [blame] | 1275 | ASSERT_EQ(std::memcmp(value, kValue2, sizeof(value)), 0); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1276 | } |
| 1277 | |
Wyatt Hepler | 6c24c06 | 2020-02-05 15:30:49 -0800 | [diff] [blame^] | 1278 | TEST_F(KeyValueStoreTest, CallingEraseTwice) { |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1279 | const uint8_t kValue = 0xDA; |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 1280 | ASSERT_EQ(Status::OK, kvs_.Put(keys[0], kValue)); |
| 1281 | ASSERT_EQ(Status::OK, kvs_.Delete(keys[0])); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1282 | uint16_t crc = CalcTestPartitionCrc(); |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 1283 | EXPECT_EQ(kvs_.Delete(keys[0]), Status::NOT_FOUND); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1284 | // Verify the flash has not changed |
| 1285 | EXPECT_EQ(crc, CalcTestPartitionCrc()); |
| 1286 | } |
| 1287 | |
| 1288 | void __attribute__((noinline)) StackHeavyPartialClean() { |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 1289 | #if 0 // TODO: No FlashSubPartition |
| 1290 | |
| 1291 | ASSERT_GE(test_partition.sector_count(), 2); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1292 | FlashSubPartition test_partition_sector1(&test_partition, 0, 1); |
| 1293 | FlashSubPartition test_partition_sector2(&test_partition, 1, 1); |
| 1294 | |
| 1295 | KeyValueStore kvs1(&test_partition_sector1); |
| 1296 | KeyValueStore kvs2(&test_partition_sector2); |
| 1297 | |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 1298 | test_partition.Erase(0, test_partition.sector_count()); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1299 | |
Wyatt Hepler | 2ad6067 | 2020-01-21 08:00:16 -0800 | [diff] [blame] | 1300 | ASSERT_EQ(Status::OK, kvs1.Enable()); |
| 1301 | ASSERT_EQ(Status::OK, kvs2.Enable()); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1302 | |
| 1303 | int values1[3] = {100, 101, 102}; |
Wyatt Hepler | 2ad6067 | 2020-01-21 08:00:16 -0800 | [diff] [blame] | 1304 | ASSERT_EQ(Status::OK, kvs1.Put(keys[0], values1[0])); |
| 1305 | ASSERT_EQ(Status::OK, kvs1.Put(keys[1], values1[1])); |
| 1306 | ASSERT_EQ(Status::OK, kvs1.Put(keys[2], values1[2])); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1307 | |
| 1308 | int values2[3] = {200, 201, 202}; |
Wyatt Hepler | 2ad6067 | 2020-01-21 08:00:16 -0800 | [diff] [blame] | 1309 | ASSERT_EQ(Status::OK, kvs2.Put(keys[0], values2[0])); |
| 1310 | ASSERT_EQ(Status::OK, kvs2.Put(keys[1], values2[1])); |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 1311 | ASSERT_EQ(Status::OK, kvs2.Delete(keys[1])); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1312 | |
| 1313 | kvs1.Disable(); |
| 1314 | kvs2.Disable(); |
| 1315 | |
| 1316 | // Key 0 is value1 in first sector, value 2 in second |
| 1317 | // Key 1 is value1 in first sector, erased in second |
| 1318 | // key 2 is only in first sector |
| 1319 | |
| 1320 | uint64_t mark_clean_count = 5; |
Wyatt Hepler | 2ad6067 | 2020-01-21 08:00:16 -0800 | [diff] [blame] | 1321 | ASSERT_EQ(Status::OK, |
| 1322 | PaddedWrite(&test_partition_sector1, |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1323 | RoundUpForAlignment(KeyValueStore::kHeaderSize), |
| 1324 | reinterpret_cast<uint8_t*>(&mark_clean_count), |
| 1325 | sizeof(uint64_t))); |
| 1326 | |
| 1327 | // Reset KVS |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 1328 | kvs_.Disable(); |
| 1329 | ASSERT_EQ(Status::OK, kvs_.Init()); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1330 | int value; |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 1331 | ASSERT_EQ(Status::OK, kvs_.Get(keys[0], &value)); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1332 | ASSERT_EQ(values2[0], value); |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 1333 | ASSERT_EQ(kvs_.Get(keys[1], &value), Status::NOT_FOUND); |
| 1334 | ASSERT_EQ(Status::OK, kvs_.Get(keys[2], &value)); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1335 | ASSERT_EQ(values1[2], value); |
| 1336 | |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 1337 | if (test_partition.sector_count() == 2) { |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 1338 | EXPECT_EQ(kvs_.PendingCleanCount(), 0u); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1339 | // Has forced a clean, mark again for next test |
| 1340 | return; // Not enough sectors to test 2 partial cleans. |
| 1341 | } else { |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 1342 | EXPECT_EQ(kvs_.PendingCleanCount(), 1u); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1343 | } |
| 1344 | |
| 1345 | mark_clean_count--; |
Wyatt Hepler | 2ad6067 | 2020-01-21 08:00:16 -0800 | [diff] [blame] | 1346 | ASSERT_EQ(Status::OK, |
| 1347 | PaddedWrite(&test_partition_sector2, |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1348 | RoundUpForAlignment(KeyValueStore::kHeaderSize), |
| 1349 | reinterpret_cast<uint8_t*>(&mark_clean_count), |
| 1350 | sizeof(uint64_t))); |
| 1351 | // Reset KVS |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 1352 | kvs_.Disable(); |
| 1353 | ASSERT_EQ(Status::OK, kvs_.Init()); |
| 1354 | EXPECT_EQ(kvs_.PendingCleanCount(), 2u); |
| 1355 | ASSERT_EQ(Status::OK, kvs_.Get(keys[0], &value)); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1356 | ASSERT_EQ(values1[0], value); |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 1357 | ASSERT_EQ(Status::OK, kvs_.Get(keys[1], &value)); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1358 | ASSERT_EQ(values1[1], value); |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 1359 | ASSERT_EQ(Status::OK, kvs_.Get(keys[2], &value)); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1360 | ASSERT_EQ(values1[2], value); |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 1361 | #endif |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1362 | } |
| 1363 | |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 1364 | // TODO: This doesn't do anything, and would be unreliable anyway. |
Wyatt Hepler | 2ad6067 | 2020-01-21 08:00:16 -0800 | [diff] [blame] | 1365 | size_t CurrentTaskStackFree() { return -1; } |
| 1366 | |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 1367 | TEST_F(KeyValueStoreTest, DISABLED_PartialClean) { |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1368 | if (CurrentTaskStackFree() < sizeof(KeyValueStore) * 2) { |
Wyatt Hepler | 2ad6067 | 2020-01-21 08:00:16 -0800 | [diff] [blame] | 1369 | PW_LOG_ERROR("Not enough stack for test, skipping"); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1370 | return; |
| 1371 | } |
| 1372 | StackHeavyPartialClean(); |
| 1373 | } |
| 1374 | |
| 1375 | void __attribute__((noinline)) StackHeavyCleanAll() { |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 1376 | #if 0 // TODO: no FlashSubPartition |
| 1377 | ASSERT_GE(test_partition.sector_count(), 2); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1378 | FlashSubPartition test_partition_sector1(&test_partition, 0, 1); |
| 1379 | |
| 1380 | KeyValueStore kvs1(&test_partition_sector1); |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 1381 | test_partition.Erase(0, test_partition.sector_count()); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1382 | |
Wyatt Hepler | 2ad6067 | 2020-01-21 08:00:16 -0800 | [diff] [blame] | 1383 | ASSERT_EQ(Status::OK, kvs1.Enable()); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1384 | |
| 1385 | int values1[3] = {100, 101, 102}; |
Wyatt Hepler | 2ad6067 | 2020-01-21 08:00:16 -0800 | [diff] [blame] | 1386 | ASSERT_EQ(Status::OK, kvs1.Put(keys[0], values1[0])); |
| 1387 | ASSERT_EQ(Status::OK, kvs1.Put(keys[1], values1[1])); |
| 1388 | ASSERT_EQ(Status::OK, |
| 1389 | kvs1.Put(keys[2], values1[2] - 100)); // force a rewrite |
| 1390 | ASSERT_EQ(Status::OK, kvs1.Put(keys[2], values1[2])); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1391 | |
| 1392 | kvs1.Disable(); |
| 1393 | |
| 1394 | uint64_t mark_clean_count = 5; |
Wyatt Hepler | 2ad6067 | 2020-01-21 08:00:16 -0800 | [diff] [blame] | 1395 | ASSERT_EQ(Status::OK, |
| 1396 | PaddedWrite(&test_partition_sector1, |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1397 | RoundUpForAlignment(KeyValueStore::kHeaderSize), |
| 1398 | reinterpret_cast<uint8_t*>(&mark_clean_count), |
| 1399 | sizeof(uint64_t))); |
| 1400 | |
| 1401 | // Reset KVS |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 1402 | kvs_.Disable(); |
| 1403 | ASSERT_EQ(Status::OK, kvs_.Init()); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1404 | int value; |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 1405 | EXPECT_EQ(kvs_.PendingCleanCount(), 1u); |
| 1406 | ASSERT_EQ(Status::OK, kvs_.CleanAll()); |
| 1407 | EXPECT_EQ(kvs_.PendingCleanCount(), 0u); |
| 1408 | ASSERT_EQ(Status::OK, kvs_.Get(keys[0], &value)); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1409 | ASSERT_EQ(values1[0], value); |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 1410 | ASSERT_EQ(Status::OK, kvs_.Get(keys[1], &value)); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1411 | ASSERT_EQ(values1[1], value); |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 1412 | ASSERT_EQ(Status::OK, kvs_.Get(keys[2], &value)); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1413 | ASSERT_EQ(values1[2], value); |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 1414 | #endif |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1415 | } |
| 1416 | |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 1417 | TEST_F(KeyValueStoreTest, DISABLED_CleanAll) { |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1418 | if (CurrentTaskStackFree() < sizeof(KeyValueStore) * 1) { |
Wyatt Hepler | 2ad6067 | 2020-01-21 08:00:16 -0800 | [diff] [blame] | 1419 | PW_LOG_ERROR("Not enough stack for test, skipping"); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1420 | return; |
| 1421 | } |
| 1422 | StackHeavyCleanAll(); |
| 1423 | } |
| 1424 | |
| 1425 | void __attribute__((noinline)) StackHeavyPartialCleanLargeCounts() { |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 1426 | #if 0 |
| 1427 | ASSERT_GE(test_partition.sector_count(), 2); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1428 | FlashSubPartition test_partition_sector1(&test_partition, 0, 1); |
| 1429 | FlashSubPartition test_partition_sector2(&test_partition, 1, 1); |
| 1430 | |
| 1431 | KeyValueStore kvs1(&test_partition_sector1); |
| 1432 | KeyValueStore kvs2(&test_partition_sector2); |
| 1433 | |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 1434 | test_partition.Erase(0, test_partition.sector_count()); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1435 | |
Wyatt Hepler | 2ad6067 | 2020-01-21 08:00:16 -0800 | [diff] [blame] | 1436 | ASSERT_EQ(Status::OK, kvs1.Enable()); |
| 1437 | ASSERT_EQ(Status::OK, kvs2.Enable()); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1438 | |
| 1439 | int values1[3] = {100, 101, 102}; |
Wyatt Hepler | 2ad6067 | 2020-01-21 08:00:16 -0800 | [diff] [blame] | 1440 | ASSERT_EQ(Status::OK, kvs1.Put(keys[0], values1[0])); |
| 1441 | ASSERT_EQ(Status::OK, kvs1.Put(keys[1], values1[1])); |
| 1442 | ASSERT_EQ(Status::OK, kvs1.Put(keys[2], values1[2])); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1443 | |
| 1444 | int values2[3] = {200, 201, 202}; |
Wyatt Hepler | 2ad6067 | 2020-01-21 08:00:16 -0800 | [diff] [blame] | 1445 | ASSERT_EQ(Status::OK, kvs2.Put(keys[0], values2[0])); |
| 1446 | ASSERT_EQ(Status::OK, kvs2.Put(keys[1], values2[1])); |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 1447 | ASSERT_EQ(Status::OK, kvs2.Delete(keys[1])); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1448 | |
| 1449 | kvs1.Disable(); |
| 1450 | kvs2.Disable(); |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 1451 | kvs_.Disable(); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1452 | |
| 1453 | // Key 0 is value1 in first sector, value 2 in second |
| 1454 | // Key 1 is value1 in first sector, erased in second |
| 1455 | // key 2 is only in first sector |
| 1456 | |
| 1457 | uint64_t mark_clean_count = 4569877515; |
Wyatt Hepler | 2ad6067 | 2020-01-21 08:00:16 -0800 | [diff] [blame] | 1458 | ASSERT_EQ(Status::OK, |
| 1459 | PaddedWrite(&test_partition_sector1, |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1460 | RoundUpForAlignment(KeyValueStore::kHeaderSize), |
| 1461 | reinterpret_cast<uint8_t*>(&mark_clean_count), |
| 1462 | sizeof(uint64_t))); |
| 1463 | |
| 1464 | // Reset KVS |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 1465 | ASSERT_EQ(Status::OK, kvs_.Init()); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1466 | int value; |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 1467 | ASSERT_EQ(Status::OK, kvs_.Get(keys[0], &value)); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1468 | ASSERT_EQ(values2[0], value); |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 1469 | ASSERT_EQ(kvs_.Get(keys[1], &value), Status::NOT_FOUND); |
| 1470 | ASSERT_EQ(Status::OK, kvs_.Get(keys[2], &value)); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1471 | ASSERT_EQ(values1[2], value); |
| 1472 | |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 1473 | if (test_partition.sector_count() == 2) { |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 1474 | EXPECT_EQ(kvs_.PendingCleanCount(), 0u); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1475 | // Has forced a clean, mark again for next test |
| 1476 | // Has forced a clean, mark again for next test |
| 1477 | return; // Not enough sectors to test 2 partial cleans. |
| 1478 | } else { |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 1479 | EXPECT_EQ(kvs_.PendingCleanCount(), 1u); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1480 | } |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 1481 | kvs_.Disable(); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1482 | |
| 1483 | mark_clean_count--; |
Wyatt Hepler | 2ad6067 | 2020-01-21 08:00:16 -0800 | [diff] [blame] | 1484 | ASSERT_EQ(Status::OK, |
| 1485 | PaddedWrite(&test_partition_sector2, |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1486 | RoundUpForAlignment(KeyValueStore::kHeaderSize), |
| 1487 | reinterpret_cast<uint8_t*>(&mark_clean_count), |
| 1488 | sizeof(uint64_t))); |
| 1489 | // Reset KVS |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 1490 | ASSERT_EQ(Status::OK, kvs_.Init()); |
| 1491 | EXPECT_EQ(kvs_.PendingCleanCount(), 2u); |
| 1492 | ASSERT_EQ(Status::OK, kvs_.Get(keys[0], &value)); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1493 | ASSERT_EQ(values1[0], value); |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 1494 | ASSERT_EQ(Status::OK, kvs_.Get(keys[1], &value)); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1495 | ASSERT_EQ(values1[1], value); |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 1496 | ASSERT_EQ(Status::OK, kvs_.Get(keys[2], &value)); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1497 | ASSERT_EQ(values1[2], value); |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 1498 | #endif |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1499 | } |
| 1500 | |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 1501 | TEST_F(KeyValueStoreTest, DISABLED_PartialCleanLargeCounts) { |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1502 | if (CurrentTaskStackFree() < sizeof(KeyValueStore) * 2) { |
Wyatt Hepler | 2ad6067 | 2020-01-21 08:00:16 -0800 | [diff] [blame] | 1503 | PW_LOG_ERROR("Not enough stack for test, skipping"); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1504 | return; |
| 1505 | } |
| 1506 | StackHeavyPartialCleanLargeCounts(); |
| 1507 | } |
| 1508 | |
| 1509 | void __attribute__((noinline)) StackHeavyRecoverNoFreeSectors() { |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 1510 | #if 0 // TODO: no FlashSubPartition |
| 1511 | ASSERT_GE(test_partition.sector_count(), 2); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1512 | FlashSubPartition test_partition_sector1(&test_partition, 0, 1); |
| 1513 | FlashSubPartition test_partition_sector2(&test_partition, 1, 1); |
| 1514 | FlashSubPartition test_partition_both(&test_partition, 0, 2); |
| 1515 | |
| 1516 | KeyValueStore kvs1(&test_partition_sector1); |
| 1517 | KeyValueStore kvs2(&test_partition_sector2); |
| 1518 | KeyValueStore kvs_both(&test_partition_both); |
| 1519 | |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 1520 | test_partition.Erase(0, test_partition.sector_count()); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1521 | |
Wyatt Hepler | 2ad6067 | 2020-01-21 08:00:16 -0800 | [diff] [blame] | 1522 | ASSERT_EQ(Status::OK, kvs1.Enable()); |
| 1523 | ASSERT_EQ(Status::OK, kvs2.Enable()); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1524 | |
| 1525 | int values[3] = {100, 101}; |
Wyatt Hepler | 2ad6067 | 2020-01-21 08:00:16 -0800 | [diff] [blame] | 1526 | ASSERT_EQ(Status::OK, kvs1.Put(keys[0], values[0])); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1527 | ASSERT_FALSE(kvs1.HasEmptySector()); |
Wyatt Hepler | 2ad6067 | 2020-01-21 08:00:16 -0800 | [diff] [blame] | 1528 | ASSERT_EQ(Status::OK, kvs2.Put(keys[1], values[1])); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1529 | ASSERT_FALSE(kvs2.HasEmptySector()); |
| 1530 | |
| 1531 | kvs1.Disable(); |
| 1532 | kvs2.Disable(); |
| 1533 | |
| 1534 | // Reset KVS |
Wyatt Hepler | 2ad6067 | 2020-01-21 08:00:16 -0800 | [diff] [blame] | 1535 | ASSERT_EQ(Status::OK, kvs_both.Enable()); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1536 | ASSERT_TRUE(kvs_both.HasEmptySector()); |
| 1537 | int value; |
Wyatt Hepler | 2ad6067 | 2020-01-21 08:00:16 -0800 | [diff] [blame] | 1538 | ASSERT_EQ(Status::OK, kvs_both.Get(keys[0], &value)); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1539 | ASSERT_EQ(values[0], value); |
Wyatt Hepler | 2ad6067 | 2020-01-21 08:00:16 -0800 | [diff] [blame] | 1540 | ASSERT_EQ(Status::OK, kvs_both.Get(keys[1], &value)); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1541 | ASSERT_EQ(values[1], value); |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 1542 | #endif |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1543 | } |
| 1544 | |
| 1545 | TEST_F(KeyValueStoreTest, RecoverNoFreeSectors) { |
| 1546 | if (CurrentTaskStackFree() < sizeof(KeyValueStore) * 3) { |
Wyatt Hepler | 2ad6067 | 2020-01-21 08:00:16 -0800 | [diff] [blame] | 1547 | PW_LOG_ERROR("Not enough stack for test, skipping"); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1548 | return; |
| 1549 | } |
| 1550 | StackHeavyRecoverNoFreeSectors(); |
| 1551 | } |
| 1552 | |
| 1553 | void __attribute__((noinline)) StackHeavyCleanOneSector() { |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 1554 | #if 0 // TODO: no FlashSubPartition |
| 1555 | ASSERT_GE(test_partition.sector_count(), 2); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1556 | FlashSubPartition test_partition_sector1(&test_partition, 0, 1); |
| 1557 | FlashSubPartition test_partition_sector2(&test_partition, 1, 1); |
| 1558 | |
| 1559 | KeyValueStore kvs1(&test_partition_sector1); |
| 1560 | |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 1561 | test_partition.Erase(0, test_partition.sector_count()); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1562 | |
Wyatt Hepler | 2ad6067 | 2020-01-21 08:00:16 -0800 | [diff] [blame] | 1563 | ASSERT_EQ(Status::OK, kvs1.Enable()); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1564 | |
| 1565 | int values[3] = {100, 101, 102}; |
Wyatt Hepler | 2ad6067 | 2020-01-21 08:00:16 -0800 | [diff] [blame] | 1566 | ASSERT_EQ(Status::OK, kvs1.Put(keys[0], values[0])); |
| 1567 | ASSERT_EQ(Status::OK, kvs1.Put(keys[1], values[1])); |
| 1568 | ASSERT_EQ(Status::OK, kvs1.Put(keys[2], values[2])); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1569 | |
| 1570 | kvs1.Disable(); |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 1571 | kvs_.Disable(); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1572 | |
| 1573 | uint64_t mark_clean_count = 1; |
Wyatt Hepler | 2ad6067 | 2020-01-21 08:00:16 -0800 | [diff] [blame] | 1574 | ASSERT_EQ(Status::OK, |
| 1575 | PaddedWrite(&test_partition_sector1, |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1576 | RoundUpForAlignment(KeyValueStore::kHeaderSize), |
| 1577 | reinterpret_cast<uint8_t*>(&mark_clean_count), |
| 1578 | sizeof(uint64_t))); |
| 1579 | |
| 1580 | // Reset KVS |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 1581 | ASSERT_EQ(Status::OK, kvs_.Init()); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1582 | |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 1583 | EXPECT_EQ(kvs_.PendingCleanCount(), 1u); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1584 | |
| 1585 | bool all_sectors_have_been_cleaned = false; |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 1586 | ASSERT_EQ(Status::OK, kvs_.CleanOneSector(&all_sectors_have_been_cleaned)); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1587 | EXPECT_EQ(all_sectors_have_been_cleaned, true); |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 1588 | EXPECT_EQ(kvs_.PendingCleanCount(), 0u); |
| 1589 | ASSERT_EQ(Status::OK, kvs_.CleanOneSector(&all_sectors_have_been_cleaned)); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1590 | EXPECT_EQ(all_sectors_have_been_cleaned, true); |
| 1591 | int value; |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 1592 | ASSERT_EQ(Status::OK, kvs_.Get(keys[0], &value)); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1593 | ASSERT_EQ(values[0], value); |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 1594 | ASSERT_EQ(Status::OK, kvs_.Get(keys[1], &value)); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1595 | ASSERT_EQ(values[1], value); |
Wyatt Hepler | 2e56887 | 2020-02-03 18:00:00 -0800 | [diff] [blame] | 1596 | ASSERT_EQ(Status::OK, kvs_.Get(keys[2], &value)); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1597 | ASSERT_EQ(values[2], value); |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 1598 | #endif |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1599 | } |
| 1600 | |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 1601 | TEST_F(KeyValueStoreTest, DISABLED_CleanOneSector) { |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1602 | if (CurrentTaskStackFree() < sizeof(KeyValueStore)) { |
Wyatt Hepler | 2ad6067 | 2020-01-21 08:00:16 -0800 | [diff] [blame] | 1603 | PW_LOG_ERROR("Not enough stack for test, skipping"); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1604 | return; |
| 1605 | } |
| 1606 | StackHeavyCleanOneSector(); |
| 1607 | } |
| 1608 | |
| 1609 | #if USE_MEMORY_BUFFER |
| 1610 | |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 1611 | TEST_F(KeyValueStoreTest, DISABLED_LargePartition) { |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1612 | if (CurrentTaskStackFree() < sizeof(KeyValueStore)) { |
Wyatt Hepler | 2ad6067 | 2020-01-21 08:00:16 -0800 | [diff] [blame] | 1613 | PW_LOG_ERROR("Not enough stack for test, skipping"); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1614 | return; |
| 1615 | } |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 1616 | KeyValueStore large_kvs(&large_test_partition, format); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1617 | |
| 1618 | const uint8_t kValue1 = 0xDA; |
| 1619 | const uint8_t kValue2 = 0x12; |
Wyatt Hepler | acaacf9 | 2020-01-24 10:58:30 -0800 | [diff] [blame] | 1620 | uint8_t value; |
| 1621 | ASSERT_EQ(Status::OK, large_kvs.Put(keys[0], kValue1)); |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 1622 | EXPECT_EQ(large_kvs.size(), 1u); |
| 1623 | ASSERT_EQ(Status::OK, large_kvs.Delete(keys[0])); |
Wyatt Hepler | acaacf9 | 2020-01-24 10:58:30 -0800 | [diff] [blame] | 1624 | EXPECT_EQ(large_kvs.Get(keys[0], &value), Status::NOT_FOUND); |
| 1625 | ASSERT_EQ(Status::OK, large_kvs.Put(keys[1], kValue1)); |
| 1626 | ASSERT_EQ(Status::OK, large_kvs.Put(keys[2], kValue2)); |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 1627 | ASSERT_EQ(Status::OK, large_kvs.Delete(keys[1])); |
Wyatt Hepler | acaacf9 | 2020-01-24 10:58:30 -0800 | [diff] [blame] | 1628 | EXPECT_EQ(Status::OK, large_kvs.Get(keys[2], &value)); |
| 1629 | EXPECT_EQ(kValue2, value); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1630 | ASSERT_EQ(large_kvs.Get(keys[1], &value), Status::NOT_FOUND); |
Wyatt Hepler | 4da1fcb | 2020-01-30 17:32:18 -0800 | [diff] [blame] | 1631 | EXPECT_EQ(large_kvs.size(), 1u); |
Wyatt Hepler | b760954 | 2020-01-24 10:29:54 -0800 | [diff] [blame] | 1632 | } |
| 1633 | #endif // USE_MEMORY_BUFFER |
| 1634 | |
Keir Mierle | 8c352dc | 2020-02-02 13:58:19 -0800 | [diff] [blame] | 1635 | TEST(KeyValueStoreEntryHeader, KeyValueSizes) { |
| 1636 | EntryHeader header; |
| 1637 | |
| 1638 | header.set_key_length(9u); |
| 1639 | EXPECT_EQ(header.key_length(), 9u); |
| 1640 | |
| 1641 | header.set_value_length(11u); |
| 1642 | EXPECT_EQ(header.value_length(), 11u); |
| 1643 | |
| 1644 | header.set_key_length(6u); |
| 1645 | header.set_value_length(100u); |
| 1646 | EXPECT_EQ(header.key_length(), 6u); |
| 1647 | EXPECT_EQ(header.value_length(), 100u); |
| 1648 | |
| 1649 | header.set_value_length(10u); |
| 1650 | EXPECT_EQ(header.key_length(), 6u); |
| 1651 | EXPECT_EQ(header.value_length(), 10u); |
| 1652 | |
| 1653 | header.set_key_length(3u); |
| 1654 | header.set_value_length(4000u); |
| 1655 | EXPECT_EQ(header.key_length(), 3u); |
| 1656 | EXPECT_EQ(header.value_length(), 4000u); |
| 1657 | } |
| 1658 | |
Wyatt Hepler | 2ad6067 | 2020-01-21 08:00:16 -0800 | [diff] [blame] | 1659 | } // namespace pw::kvs |