Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / third_party / pigweed / repo / pw_blob_store / blob_store_deferred_write_test.cc
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 <array>
16 #include <cstddef>
17 #include <cstring>
18 #include <span>
19
20 #include "gtest/gtest.h"
21 #include "pw_blob_store/blob_store.h"
22 #include "pw_kvs/crc16_checksum.h"
23 #include "pw_kvs/fake_flash_memory.h"
24 #include "pw_kvs/flash_memory.h"
25 #include "pw_kvs/test_key_value_store.h"
26 #include "pw_log/log.h"
27 #include "pw_random/xor_shift.h"
28
29 namespace pw::blob_store {
30 namespace {
31
32 class DeferredWriteTest : public ::testing::Test {
33  protected:
34   DeferredWriteTest() : flash_(kFlashAlignment), partition_(&flash_) {}
35
36   void InitFlashTo(std::span<const std::byte> contents) {
37     partition_.Erase();
38     std::memcpy(flash_.buffer().data(), contents.data(), contents.size());
39   }
40
41   void InitBufferToRandom(uint64_t seed) {
42     partition_.Erase();
43     random::XorShiftStarRng64 rng(seed);
44     rng.Get(buffer_);
45   }
46
47   void InitBufferToFill(char fill) {
48     partition_.Erase();
49     std::memset(buffer_.data(), fill, buffer_.size());
50   }
51
52   // Fill the source buffer with random pattern based on given seed, written to
53   // BlobStore in specified chunk size.
54   void ChunkWriteTest(size_t chunk_size, size_t flush_interval) {
55     constexpr size_t kWriteSize = 64;
56     kvs::ChecksumCrc16 checksum;
57
58     size_t bytes_since_flush = 0;
59
60     char name[16] = {};
61     snprintf(name, sizeof(name), "Blob%u", static_cast<unsigned>(chunk_size));
62
63     BlobStoreBuffer<kBufferSize> blob(
64         name, partition_, &checksum, kvs::TestKvs(), kWriteSize);
65     EXPECT_EQ(OkStatus(), blob.Init());
66
67     BlobStore::DeferredWriter writer(blob);
68     EXPECT_EQ(OkStatus(), writer.Open());
69
70     ByteSpan source = buffer_;
71     while (source.size_bytes() > 0) {
72       const size_t write_size = std::min(source.size_bytes(), chunk_size);
73
74       PW_LOG_DEBUG("Do write of %u bytes, %u bytes remain",
75                    static_cast<unsigned>(write_size),
76                    static_cast<unsigned>(source.size_bytes()));
77
78       ASSERT_EQ(OkStatus(), writer.Write(source.first(write_size)));
79       // TODO: Add check that the write did not go to flash yet.
80
81       source = source.subspan(write_size);
82       bytes_since_flush += write_size;
83
84       if (bytes_since_flush >= flush_interval) {
85         bytes_since_flush = 0;
86         ASSERT_EQ(OkStatus(), writer.Flush());
87       }
88     }
89
90     EXPECT_EQ(OkStatus(), writer.Close());
91
92     // Use reader to check for valid data.
93     BlobStore::BlobReader reader(blob);
94     ASSERT_EQ(OkStatus(), reader.Open());
95     Result<ConstByteSpan> result = reader.GetMemoryMappedBlob();
96     ASSERT_TRUE(result.ok());
97     VerifyFlash(result.value());
98     EXPECT_EQ(OkStatus(), reader.Close());
99   }
100
101   void VerifyFlash(ConstByteSpan verify_bytes) {
102     // Should be defined as same size.
103     EXPECT_EQ(buffer_.size(), flash_.buffer().size_bytes());
104
105     // Can't allow it to march off the end of buffer_.
106     ASSERT_LE(verify_bytes.size_bytes(), buffer_.size());
107
108     for (size_t i = 0; i < verify_bytes.size_bytes(); i++) {
109       EXPECT_EQ(buffer_[i], verify_bytes[i]);
110     }
111   }
112
113   static constexpr size_t kFlashAlignment = 16;
114   static constexpr size_t kSectorSize = 1024;
115   static constexpr size_t kSectorCount = 4;
116   static constexpr size_t kBufferSize = 2 * kSectorSize;
117
118   kvs::FakeFlashMemoryBuffer<kSectorSize, kSectorCount> flash_;
119   kvs::FlashPartition partition_;
120   std::array<std::byte, kSectorCount * kSectorSize> buffer_;
121 };
122
123 TEST_F(DeferredWriteTest, ChunkWrite1) {
124   InitBufferToRandom(0x8675309);
125   ChunkWriteTest(1, 16);
126 }
127
128 TEST_F(DeferredWriteTest, ChunkWrite2) {
129   InitBufferToRandom(0x8675);
130   ChunkWriteTest(2, 16);
131 }
132
133 TEST_F(DeferredWriteTest, ChunkWrite3) {
134   InitBufferToFill(0);
135   ChunkWriteTest(3, 16);
136 }
137
138 TEST_F(DeferredWriteTest, ChunkWrite4) {
139   InitBufferToFill(1);
140   ChunkWriteTest(4, 64);
141 }
142
143 TEST_F(DeferredWriteTest, ChunkWrite5) {
144   InitBufferToFill(0xff);
145   ChunkWriteTest(5, 64);
146 }
147
148 TEST_F(DeferredWriteTest, ChunkWrite16) {
149   InitBufferToRandom(0x86);
150   ChunkWriteTest(16, 128);
151 }
152
153 TEST_F(DeferredWriteTest, ChunkWrite64) {
154   InitBufferToRandom(0x9);
155   ChunkWriteTest(64, 128);
156 }
157
158 TEST_F(DeferredWriteTest, ChunkWrite64FullBufferFill) {
159   InitBufferToRandom(0x9);
160   ChunkWriteTest(64, kBufferSize);
161 }
162
163 TEST_F(DeferredWriteTest, ChunkWrite256) {
164   InitBufferToRandom(0x12345678);
165   ChunkWriteTest(256, 256);
166 }
167
168 // TODO: test that has dirty flash, invalidated blob, open writer, invalidate
169 // (not erase) and start writing (does the auto/implicit erase).
170
171 // TODO: test that has dirty flash, invalidated blob, open writer, explicit
172 // erase and start writing.
173
174 // TODO: test start with dirty flash/invalid blob, open writer, write, close.
175 // Verifies erase logic when write buffer has contents.
176
177 }  // namespace
178 }  // namespace pw::blob_store