xref: /aosp_15_r20/external/pigweed/pw_blob_store/flat_file_system_entry_test.cc (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1 // Copyright 2021 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_blob_store/flat_file_system_entry.h"
16 
17 #include <array>
18 #include <cstddef>
19 #include <cstring>
20 
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_random/xor_shift.h"
27 #include "pw_span/span.h"
28 #include "pw_sync/mutex.h"
29 #include "pw_unit_test/framework.h"
30 
31 namespace pw::blob_store {
32 namespace {
33 
34 class FlatFileSystemBlobStoreEntryTest : public ::testing::Test {
35  protected:
36   static constexpr char kBlobTitle[] = "TestBlobBlock";
37   static constexpr size_t kBufferSize = 64;
38 
FlatFileSystemBlobStoreEntryTest()39   FlatFileSystemBlobStoreEntryTest()
40       : flash_(kFlashAlignment),
41         partition_(&flash_),
42         metadata_buffer_(),
43         source_buffer_(),
44         checksum_(),
45         blob_(kBlobTitle, partition_, &checksum_, kvs::TestKvs(), kBufferSize) {
46   }
47 
SetUp()48   void SetUp() override { ASSERT_EQ(OkStatus(), blob_.Init()); }
49 
InitSourceBufferToRandom(uint64_t seed,size_t init_size_bytes=kBlobDataSize)50   void InitSourceBufferToRandom(uint64_t seed,
51                                 size_t init_size_bytes = kBlobDataSize) {
52     ASSERT_LE(init_size_bytes, source_buffer_.size());
53     random::XorShiftStarRng64 rng(seed);
54 
55     std::memset(source_buffer_.data(),
56                 static_cast<int>(flash_.erased_memory_content()),
57                 source_buffer_.size());
58     rng.Get(span(source_buffer_).first(init_size_bytes));
59   }
60 
61   // Fill the source buffer with random pattern based on given seed, written to
62   // BlobStore in specified chunk size.
WriteTestBlock(std::string_view file_name,size_t write_size_bytes)63   void WriteTestBlock(std::string_view file_name, size_t write_size_bytes) {
64     ASSERT_LE(write_size_bytes, source_buffer_.size());
65 
66     ConstByteSpan write_data = span(source_buffer_).first(write_size_bytes);
67 
68     BlobStore::BlobWriter writer(blob_, metadata_buffer_);
69     EXPECT_EQ(OkStatus(), writer.Open());
70     ASSERT_EQ(OkStatus(), writer.SetFileName(file_name));
71     ASSERT_EQ(OkStatus(), writer.Write(write_data));
72     EXPECT_EQ(OkStatus(), writer.Close());
73 
74     // Use reader to check for valid data.
75     BlobStore::BlobReader reader(blob_);
76     ASSERT_EQ(OkStatus(), reader.Open());
77     Result<ConstByteSpan> result = reader.GetMemoryMappedBlob();
78     ASSERT_TRUE(result.ok());
79     EXPECT_EQ(write_size_bytes, result.value().size_bytes());
80     EXPECT_EQ(OkStatus(), reader.Close());
81   }
82 
83   static constexpr size_t kFlashAlignment = 16;
84   static constexpr size_t kSectorSize = 2048;
85   static constexpr size_t kSectorCount = 2;
86   static constexpr size_t kBlobDataSize = (kSectorCount * kSectorSize);
87   static constexpr size_t kMaxFileNameLength = 32;
88   static constexpr size_t kMetadataBufferSize =
89       BlobStore::BlobWriter::RequiredMetadataBufferSize(kMaxFileNameLength);
90 
91   kvs::FakeFlashMemoryBuffer<kSectorSize, kSectorCount> flash_;
92   kvs::FlashPartition partition_;
93   std::array<std::byte, kMetadataBufferSize> metadata_buffer_;
94   std::array<std::byte, kBlobDataSize> source_buffer_;
95   kvs::ChecksumCrc16 checksum_;
96   BlobStoreBuffer<kBufferSize> blob_;
97 };
98 
TEST_F(FlatFileSystemBlobStoreEntryTest,BasicProperties)99 TEST_F(FlatFileSystemBlobStoreEntryTest, BasicProperties) {
100   constexpr size_t kWrittenDataSizeBytes = 104;
101   constexpr uint32_t kExpectedFileId = 0x731ACAC0;
102   constexpr FlatFileSystemBlobStoreEntry::FilePermissions kExpectedPermissions =
103       FlatFileSystemBlobStoreEntry::FilePermissions::READ;
104 
105   constexpr std::string_view kFileName("my_file_1.bin");
106   InitSourceBufferToRandom(0x5C4CA189);
107   WriteTestBlock(kFileName, kWrittenDataSizeBytes);
108   std::array<char, kMaxFileNameLength> tmp_buffer = {};
109   static_assert(kFileName.size() <= tmp_buffer.size());
110 
111   sync::VirtualMutex blob_store_mutex;
112   FlatFileSystemBlobStoreEntry blob_store_file(
113       kExpectedFileId, kExpectedPermissions, blob_, blob_store_mutex);
114 
115   StatusWithSize sws = blob_store_file.Name(tmp_buffer);
116   ASSERT_EQ(OkStatus(), sws.status());
117 
118   const int comparison =
119       memcmp(tmp_buffer.data(), kFileName.data(), sws.size());
120   EXPECT_EQ(0, comparison);
121   EXPECT_EQ(kWrittenDataSizeBytes, blob_store_file.SizeBytes());
122   EXPECT_EQ(kExpectedPermissions, blob_store_file.Permissions());
123   EXPECT_EQ(kExpectedFileId, blob_store_file.FileId());
124 }
125 
TEST_F(FlatFileSystemBlobStoreEntryTest,Delete)126 TEST_F(FlatFileSystemBlobStoreEntryTest, Delete) {
127   constexpr size_t kWrittenDataSizeBytes = 104;
128   constexpr uint32_t kExpectedFileId = 0x87ED0EF2;
129   constexpr FlatFileSystemBlobStoreEntry::FilePermissions kExpectedPermissions =
130       FlatFileSystemBlobStoreEntry::FilePermissions::READ;
131 
132   constexpr std::string_view kFileName("my_file_1.bin");
133   InitSourceBufferToRandom(0x5C4CA189);
134   WriteTestBlock(kFileName, kWrittenDataSizeBytes);
135 
136   sync::VirtualMutex blob_store_mutex;
137   FlatFileSystemBlobStoreEntry blob_store_file(
138       kExpectedFileId, kExpectedPermissions, blob_, blob_store_mutex);
139 
140   ASSERT_EQ(OkStatus(), blob_store_file.Delete());
141 
142   BlobStore::BlobReader reader(blob_);
143   // Failed precondition is the expected return value when a BlobStore is opened
144   // for reading and is empty.
145   ASSERT_EQ(Status::FailedPrecondition(), reader.Open());
146 }
147 
TEST_F(FlatFileSystemBlobStoreEntryTest,NoData)148 TEST_F(FlatFileSystemBlobStoreEntryTest, NoData) {
149   constexpr uint32_t kExpectedFileId = 0x1;
150   constexpr FlatFileSystemBlobStoreEntry::FilePermissions kExpectedPermissions =
151       FlatFileSystemBlobStoreEntry::FilePermissions::READ;
152 
153   // Ensure the BlobStore is erased.
154   ASSERT_EQ(OkStatus(), partition_.Erase());
155 
156   sync::VirtualMutex blob_store_mutex;
157   FlatFileSystemBlobStoreEntry blob_store_file(
158       kExpectedFileId, kExpectedPermissions, blob_, blob_store_mutex);
159 
160   std::array<char, kMaxFileNameLength> tmp_buffer = {};
161   StatusWithSize sws = blob_store_file.Name(tmp_buffer);
162   EXPECT_EQ(Status::NotFound(), sws.status());
163   EXPECT_EQ(0u, sws.size());
164 }
165 
166 }  // namespace
167 }  // namespace pw::blob_store
168