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