blob: 5b35df22fff8b300bf3df670b181a1587beae34a [file] [log] [blame]
David Rogers96922572020-08-04 10:24:57 -07001// 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_blob_store/blob_store.h"
16
17#include <array>
18#include <cstddef>
19#include <cstring>
20#include <span>
21
22#include "gtest/gtest.h"
23#include "pw_kvs/crc16_checksum.h"
24#include "pw_kvs/fake_flash_memory.h"
25#include "pw_kvs/flash_memory.h"
26#include "pw_kvs/test_key_value_store.h"
27#include "pw_log/log.h"
28#include "pw_random/xor_shift.h"
29
David Rogers96571412021-11-05 03:30:35 -070030#ifndef PW_FLASH_TEST_ALIGNMENT
31#define PW_FLASH_TEST_ALIGNMENT 1
32#endif
33
David Rogers96922572020-08-04 10:24:57 -070034namespace pw::blob_store {
35namespace {
36
37class BlobStoreTest : public ::testing::Test {
38 protected:
Armando Montanez28ad6f42021-08-30 16:23:57 -070039 static constexpr char kBlobTitle[] = "TestBlobBlock";
40
David Rogers96922572020-08-04 10:24:57 -070041 BlobStoreTest() : flash_(kFlashAlignment), partition_(&flash_) {}
42
43 void InitFlashTo(std::span<const std::byte> contents) {
Adrien Larbanetd1ca56c2021-06-10 14:20:45 +000044 partition_.Erase()
45 .IgnoreError(); // TODO(pwbug/387): Handle Status properly
David Rogers96922572020-08-04 10:24:57 -070046 std::memcpy(flash_.buffer().data(), contents.data(), contents.size());
47 }
48
David Rogers22f7b3e2020-10-07 23:58:11 -070049 void InitSourceBufferToRandom(uint64_t seed,
50 size_t init_size_bytes = kBlobDataSize) {
51 ASSERT_LE(init_size_bytes, source_buffer_.size());
David Rogers96922572020-08-04 10:24:57 -070052 random::XorShiftStarRng64 rng(seed);
David Rogers22f7b3e2020-10-07 23:58:11 -070053
54 std::memset(source_buffer_.data(),
55 static_cast<int>(flash_.erased_memory_content()),
56 source_buffer_.size());
Adrien Larbanetd1ca56c2021-06-10 14:20:45 +000057 rng.Get(std::span(source_buffer_).first(init_size_bytes))
58 .IgnoreError(); // TODO(pwbug/387): Handle Status properly
David Rogers5aa32ab2020-09-08 14:39:24 -070059 }
60
David Rogers22f7b3e2020-10-07 23:58:11 -070061 void InitSourceBufferToFill(char fill,
62 size_t fill_size_bytes = kBlobDataSize) {
63 ASSERT_LE(fill_size_bytes, source_buffer_.size());
64 std::memset(source_buffer_.data(),
65 static_cast<int>(flash_.erased_memory_content()),
66 source_buffer_.size());
67 std::memset(source_buffer_.data(), fill, fill_size_bytes);
David Rogers96922572020-08-04 10:24:57 -070068 }
69
70 // Fill the source buffer with random pattern based on given seed, written to
71 // BlobStore in specified chunk size.
David Rogers22f7b3e2020-10-07 23:58:11 -070072 void WriteTestBlock(size_t write_size_bytes = kBlobDataSize) {
73 ASSERT_LE(write_size_bytes, source_buffer_.size());
David Rogers96922572020-08-04 10:24:57 -070074 constexpr size_t kBufferSize = 256;
75 kvs::ChecksumCrc16 checksum;
76
David Rogers22f7b3e2020-10-07 23:58:11 -070077 ConstByteSpan write_data =
78 std::span(source_buffer_).first(write_size_bytes);
79
David Rogers96922572020-08-04 10:24:57 -070080 BlobStoreBuffer<kBufferSize> blob(
Armando Montanez28ad6f42021-08-30 16:23:57 -070081 kBlobTitle, partition_, &checksum, kvs::TestKvs(), kBufferSize);
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -080082 EXPECT_EQ(OkStatus(), blob.Init());
David Rogers96922572020-08-04 10:24:57 -070083
Armando Montanez0e8aff82021-09-30 13:21:12 -070084 BlobStore::BlobWriterWithBuffer writer(blob);
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -080085 EXPECT_EQ(OkStatus(), writer.Open());
86 ASSERT_EQ(OkStatus(), writer.Write(write_data));
87 EXPECT_EQ(OkStatus(), writer.Close());
David Rogers96922572020-08-04 10:24:57 -070088
89 // Use reader to check for valid data.
David Rogers10395842020-09-16 15:39:35 -070090 BlobStore::BlobReader reader(blob);
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -080091 ASSERT_EQ(OkStatus(), reader.Open());
David Rogers0fadf442020-09-18 10:38:15 -070092 Result<ConstByteSpan> result = reader.GetMemoryMappedBlob();
David Rogers96922572020-08-04 10:24:57 -070093 ASSERT_TRUE(result.ok());
David Rogers22f7b3e2020-10-07 23:58:11 -070094 EXPECT_EQ(write_size_bytes, result.value().size_bytes());
David Rogers84e0dec2020-11-24 14:33:18 -080095 VerifyFlash(result.value().first(write_size_bytes));
96 VerifyFlash(flash_.buffer().first(write_size_bytes));
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -080097 EXPECT_EQ(OkStatus(), reader.Close());
David Rogers96922572020-08-04 10:24:57 -070098 }
99
David Rogers10395842020-09-16 15:39:35 -0700100 // Open a new blob instance and read the blob using the given read chunk size.
101 void ChunkReadTest(size_t read_chunk_size) {
102 kvs::ChecksumCrc16 checksum;
103
104 VerifyFlash(flash_.buffer());
105
David Rogers1f08acb2020-11-17 23:11:58 -0800106 constexpr size_t kBufferSize = 16;
107 BlobStoreBuffer<kBufferSize> blob(
Armando Montanez28ad6f42021-08-30 16:23:57 -0700108 kBlobTitle, partition_, &checksum, kvs::TestKvs(), kBufferSize);
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800109 EXPECT_EQ(OkStatus(), blob.Init());
David Rogers10395842020-09-16 15:39:35 -0700110
111 // Use reader to check for valid data.
112 BlobStore::BlobReader reader1(blob);
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800113 ASSERT_EQ(OkStatus(), reader1.Open());
Ewout van Bekkumfa1fc662020-10-16 16:11:13 -0700114 Result<ConstByteSpan> possible_blob = reader1.GetMemoryMappedBlob();
115 ASSERT_TRUE(possible_blob.ok());
116 VerifyFlash(possible_blob.value());
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800117 EXPECT_EQ(OkStatus(), reader1.Close());
David Rogers10395842020-09-16 15:39:35 -0700118
119 BlobStore::BlobReader reader(blob);
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800120 ASSERT_EQ(OkStatus(), reader.Open());
David Rogers10395842020-09-16 15:39:35 -0700121
David Rogers84e0dec2020-11-24 14:33:18 -0800122 std::array<std::byte, kBlobDataSize> read_buffer;
David Rogers10395842020-09-16 15:39:35 -0700123
David Rogers84e0dec2020-11-24 14:33:18 -0800124 ByteSpan read_span = read_buffer;
David Rogers10395842020-09-16 15:39:35 -0700125 while (read_span.size_bytes() > 0) {
126 size_t read_size = std::min(read_span.size_bytes(), read_chunk_size);
127
128 PW_LOG_DEBUG("Do write of %u bytes, %u bytes remain",
129 static_cast<unsigned>(read_size),
130 static_cast<unsigned>(read_span.size_bytes()));
131
132 ASSERT_EQ(read_span.size_bytes(), reader.ConservativeReadLimit());
133 auto result = reader.Read(read_span.first(read_size));
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800134 ASSERT_EQ(result.status(), OkStatus());
David Rogers10395842020-09-16 15:39:35 -0700135 read_span = read_span.subspan(read_size);
136 }
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800137 EXPECT_EQ(OkStatus(), reader.Close());
David Rogers10395842020-09-16 15:39:35 -0700138
David Rogers84e0dec2020-11-24 14:33:18 -0800139 VerifyFlash(read_buffer);
David Rogers10395842020-09-16 15:39:35 -0700140 }
141
David Rogers0fadf442020-09-18 10:38:15 -0700142 void VerifyFlash(ConstByteSpan verify_bytes, size_t offset = 0) {
David Rogers96922572020-08-04 10:24:57 -0700143 // Should be defined as same size.
David Rogers5aa32ab2020-09-08 14:39:24 -0700144 EXPECT_EQ(source_buffer_.size(), flash_.buffer().size_bytes());
David Rogers96922572020-08-04 10:24:57 -0700145
David Rogers5aa32ab2020-09-08 14:39:24 -0700146 // Can't allow it to march off the end of source_buffer_.
David Rogers10395842020-09-16 15:39:35 -0700147 ASSERT_LE((verify_bytes.size_bytes() + offset), source_buffer_.size());
David Rogers96922572020-08-04 10:24:57 -0700148
149 for (size_t i = 0; i < verify_bytes.size_bytes(); i++) {
David Rogers10395842020-09-16 15:39:35 -0700150 ASSERT_EQ(source_buffer_[i + offset], verify_bytes[i]);
David Rogers96922572020-08-04 10:24:57 -0700151 }
152 }
153
David Rogers96571412021-11-05 03:30:35 -0700154 static constexpr size_t kFlashAlignment = PW_FLASH_TEST_ALIGNMENT;
David Rogers96922572020-08-04 10:24:57 -0700155 static constexpr size_t kSectorSize = 2048;
156 static constexpr size_t kSectorCount = 2;
David Rogers10395842020-09-16 15:39:35 -0700157 static constexpr size_t kBlobDataSize = (kSectorCount * kSectorSize);
David Rogers96922572020-08-04 10:24:57 -0700158
159 kvs::FakeFlashMemoryBuffer<kSectorSize, kSectorCount> flash_;
160 kvs::FlashPartition partition_;
David Rogers10395842020-09-16 15:39:35 -0700161 std::array<std::byte, kBlobDataSize> source_buffer_;
David Rogers96922572020-08-04 10:24:57 -0700162};
163
164TEST_F(BlobStoreTest, Init_Ok) {
David Rogers22f7b3e2020-10-07 23:58:11 -0700165 // TODO: Do init test with flash/kvs explicitly in the different possible
166 // entry states.
David Rogers1f08acb2020-11-17 23:11:58 -0800167 constexpr size_t kBufferSize = 256;
168 BlobStoreBuffer<kBufferSize> blob(
169 "Blob_OK", partition_, nullptr, kvs::TestKvs(), kBufferSize);
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800170 EXPECT_EQ(OkStatus(), blob.Init());
David Rogers96922572020-08-04 10:24:57 -0700171}
172
Wyatt Heplerad04bb02021-08-23 14:59:39 -0700173TEST_F(BlobStoreTest, Writer_ConservativeLimits) {
174 constexpr size_t kBufferSize = 256;
175 BlobStoreBuffer<kBufferSize> blob(
176 "Blob_OK", partition_, nullptr, kvs::TestKvs(), kBufferSize);
177 ASSERT_EQ(OkStatus(), blob.Init());
178
Armando Montanez0e8aff82021-09-30 13:21:12 -0700179 BlobStore::BlobWriterWithBuffer writer(blob);
Wyatt Heplerad04bb02021-08-23 14:59:39 -0700180 ASSERT_EQ(OkStatus(), writer.Open());
181 EXPECT_EQ(writer.ConservativeReadLimit(), 0u);
182 EXPECT_EQ(writer.ConservativeWriteLimit(), kSectorSize * kSectorCount);
183 ASSERT_EQ(OkStatus(), writer.Close());
184
Armando Montanez0e8aff82021-09-30 13:21:12 -0700185 BlobStore::DeferredWriterWithBuffer deferred_writer(blob);
Wyatt Heplerad04bb02021-08-23 14:59:39 -0700186 ASSERT_EQ(OkStatus(), deferred_writer.Open());
187 EXPECT_EQ(deferred_writer.ConservativeReadLimit(), 0u);
188 EXPECT_EQ(deferred_writer.ConservativeWriteLimit(), kBufferSize);
189}
190
David Rogersdd259042021-11-05 00:14:02 -0700191// Write to the blob using a flash_write_size_bytes smaller than the
192// buffer size. Use Write operations smaller than flash_write_size_bytes
193// to ensure it checks the internal buffering path.
194TEST_F(BlobStoreTest, OversizedWriteBuffer) {
195 size_t write_size_bytes = 8;
196 ASSERT_LE(write_size_bytes, source_buffer_.size());
197 constexpr size_t kBufferSize = 256;
198 kvs::ChecksumCrc16 checksum;
199
200 InitSourceBufferToRandom(0x123d123);
201
202 ConstByteSpan write_data = std::span(source_buffer_);
203 ConstByteSpan original_source = std::span(source_buffer_);
204
205 EXPECT_EQ(OkStatus(), partition_.Erase());
206
207 BlobStoreBuffer<kBufferSize> blob(
208 kBlobTitle, partition_, &checksum, kvs::TestKvs(), 64);
209 EXPECT_EQ(OkStatus(), blob.Init());
210
211 BlobStore::BlobWriterWithBuffer writer(blob);
212 EXPECT_EQ(OkStatus(), writer.Open());
213 while (write_data.size_bytes() > 0) {
214 ASSERT_EQ(OkStatus(), writer.Write(write_data.first(write_size_bytes)));
215 write_data = write_data.subspan(write_size_bytes);
216 }
217 EXPECT_EQ(OkStatus(), writer.Close());
218
219 // Use reader to check for valid data.
220 BlobStore::BlobReader reader(blob);
221 ASSERT_EQ(OkStatus(), reader.Open());
222 Result<ConstByteSpan> result = reader.GetMemoryMappedBlob();
223 ASSERT_TRUE(result.ok());
224 EXPECT_EQ(original_source.size_bytes(), result.value().size_bytes());
225 VerifyFlash(result.value());
226 VerifyFlash(flash_.buffer());
227 EXPECT_EQ(OkStatus(), reader.Close());
228}
229
Wyatt Heplerad04bb02021-08-23 14:59:39 -0700230TEST_F(BlobStoreTest, Reader_ConservativeLimits) {
231 InitSourceBufferToRandom(0x11309);
232 WriteTestBlock();
233
234 kvs::ChecksumCrc16 checksum;
235 constexpr size_t kBufferSize = 16;
236 BlobStoreBuffer<kBufferSize> blob(
237 "TestBlobBlock", partition_, &checksum, kvs::TestKvs(), kBufferSize);
238 EXPECT_EQ(OkStatus(), blob.Init());
David Rogers2835cf62022-03-10 20:23:20 -0800239 EXPECT_TRUE(blob.HasData());
Wyatt Heplerad04bb02021-08-23 14:59:39 -0700240 BlobStore::BlobReader reader(blob);
241 ASSERT_EQ(OkStatus(), reader.Open());
242
243 EXPECT_EQ(kBlobDataSize, reader.ConservativeReadLimit());
244 EXPECT_EQ(0u, reader.ConservativeWriteLimit());
245}
246
David Rogers84e0dec2020-11-24 14:33:18 -0800247TEST_F(BlobStoreTest, IsOpen) {
David Rogers1f08acb2020-11-17 23:11:58 -0800248 constexpr size_t kBufferSize = 256;
249 BlobStoreBuffer<kBufferSize> blob(
250 "Blob_open", partition_, nullptr, kvs::TestKvs(), kBufferSize);
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800251 EXPECT_EQ(OkStatus(), blob.Init());
David Rogers84e0dec2020-11-24 14:33:18 -0800252
Armando Montanez0e8aff82021-09-30 13:21:12 -0700253 BlobStore::DeferredWriterWithBuffer deferred_writer(blob);
David Rogers84e0dec2020-11-24 14:33:18 -0800254 EXPECT_EQ(false, deferred_writer.IsOpen());
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800255 EXPECT_EQ(OkStatus(), deferred_writer.Open());
David Rogers84e0dec2020-11-24 14:33:18 -0800256 EXPECT_EQ(true, deferred_writer.IsOpen());
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800257 EXPECT_EQ(OkStatus(), deferred_writer.Close());
David Rogers84e0dec2020-11-24 14:33:18 -0800258 EXPECT_EQ(false, deferred_writer.IsOpen());
259
Armando Montanez0e8aff82021-09-30 13:21:12 -0700260 BlobStore::BlobWriterWithBuffer writer(blob);
David Rogers84e0dec2020-11-24 14:33:18 -0800261 EXPECT_EQ(false, writer.IsOpen());
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800262 EXPECT_EQ(OkStatus(), writer.Open());
David Rogers84e0dec2020-11-24 14:33:18 -0800263 EXPECT_EQ(true, writer.IsOpen());
264
David Rogers2835cf62022-03-10 20:23:20 -0800265 EXPECT_FALSE(blob.HasData());
266
David Rogers84e0dec2020-11-24 14:33:18 -0800267 // Need to write something, so the blob reader is able to open.
268 std::array<std::byte, 64> tmp_buffer = {};
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800269 EXPECT_EQ(OkStatus(), writer.Write(tmp_buffer));
270 EXPECT_EQ(OkStatus(), writer.Close());
David Rogers84e0dec2020-11-24 14:33:18 -0800271 EXPECT_EQ(false, writer.IsOpen());
272
David Rogers2835cf62022-03-10 20:23:20 -0800273 EXPECT_TRUE(blob.HasData());
David Rogers84e0dec2020-11-24 14:33:18 -0800274 BlobStore::BlobReader reader(blob);
275 EXPECT_EQ(false, reader.IsOpen());
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800276 ASSERT_EQ(OkStatus(), reader.Open());
David Rogers84e0dec2020-11-24 14:33:18 -0800277 EXPECT_EQ(true, reader.IsOpen());
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800278 EXPECT_EQ(OkStatus(), reader.Close());
David Rogers84e0dec2020-11-24 14:33:18 -0800279 EXPECT_EQ(false, reader.IsOpen());
280}
281
David Rogers96571412021-11-05 03:30:35 -0700282// Write to the blob using no write buffer size. Write operations must be
283// multiples of flash_write_size_bytes.
284TEST_F(BlobStoreTest, NoWriteBuffer_1Alignment) {
285 if (kFlashAlignment > 1) {
286 // Test not valid for flash alignments greater than 1.
287 return;
288 }
289
290 const size_t kWriteSizeBytes = 1;
291 kvs::ChecksumCrc16 checksum;
292
293 InitSourceBufferToRandom(0xaabd123);
294
295 ConstByteSpan write_data = std::span(source_buffer_);
296 ConstByteSpan original_source = std::span(source_buffer_);
297
298 EXPECT_EQ(OkStatus(), partition_.Erase());
299
300 BlobStore blob(kBlobTitle,
301 partition_,
302 &checksum,
303 kvs::TestKvs(),
304 std::span<std::byte>(),
305 kWriteSizeBytes);
306 EXPECT_EQ(OkStatus(), blob.Init());
307
308 BlobStore::BlobWriterWithBuffer writer(blob);
309 EXPECT_EQ(OkStatus(), writer.Open());
310
311 size_t test_write_size[] = {1, 1, 2, 4, 32, 128};
312
313 for (size_t size : test_write_size) {
314 ASSERT_EQ(OkStatus(), writer.Write(write_data.first(size)));
315 write_data = write_data.subspan(size);
316 }
317
318 while (write_data.size_bytes() > 0) {
319 const size_t finish_write_size = 8;
320 ASSERT_EQ(OkStatus(), writer.Write(write_data.first(finish_write_size)));
321 write_data = write_data.subspan(finish_write_size);
322 }
323 EXPECT_EQ(write_data.size_bytes(), 0U);
324 EXPECT_EQ(OkStatus(), writer.Close());
325
326 // Use reader to check for valid data.
327 BlobStore::BlobReader reader(blob);
328 ASSERT_EQ(OkStatus(), reader.Open());
329 Result<ConstByteSpan> result = reader.GetMemoryMappedBlob();
330 ASSERT_TRUE(result.ok());
331 EXPECT_EQ(original_source.size_bytes(), result.value().size_bytes());
332 VerifyFlash(result.value());
333 VerifyFlash(flash_.buffer());
334 EXPECT_EQ(OkStatus(), reader.Close());
335}
336
337// Write to the blob using no write buffer size. Write operations must be
338// multiples of flash_write_size_bytes.
339TEST_F(BlobStoreTest, NoWriteBuffer_16Alignment) {
340 if (kFlashAlignment > 16) {
341 // Test not valid for flash alignments greater than 16.
342 return;
343 }
344
345 const size_t kWriteSizeBytes = 16;
346 kvs::ChecksumCrc16 checksum;
347
348 InitSourceBufferToRandom(0x6745d123);
349
350 ConstByteSpan write_data = std::span(source_buffer_);
351 ConstByteSpan original_source = std::span(source_buffer_);
352
353 EXPECT_EQ(OkStatus(), partition_.Erase());
354
355 BlobStore blob(kBlobTitle,
356 partition_,
357 &checksum,
358 kvs::TestKvs(),
359 std::span<std::byte>(),
360 kWriteSizeBytes);
361 EXPECT_EQ(OkStatus(), blob.Init());
362
363 BlobStore::BlobWriterWithBuffer writer(blob);
364 EXPECT_EQ(OkStatus(), writer.Open());
365 ASSERT_EQ(Status::InvalidArgument(), writer.Write(write_data.first(1)));
366 ASSERT_EQ(Status::InvalidArgument(),
367 writer.Write(write_data.first(kWriteSizeBytes / 2)));
368
369 ASSERT_EQ(OkStatus(), writer.Write(write_data.first(4 * kWriteSizeBytes)));
370 write_data = write_data.subspan(4 * kWriteSizeBytes);
371
372 ASSERT_EQ(Status::InvalidArgument(), writer.Write(write_data.first(1)));
373 ASSERT_EQ(Status::InvalidArgument(),
374 writer.Write(write_data.first(kWriteSizeBytes / 2)));
375
376 while (write_data.size_bytes() > 0) {
377 ASSERT_EQ(OkStatus(), writer.Write(write_data.first(kWriteSizeBytes)));
378 write_data = write_data.subspan(kWriteSizeBytes);
379 }
380 EXPECT_EQ(OkStatus(), writer.Close());
381
382 // Use reader to check for valid data.
383 BlobStore::BlobReader reader(blob);
384 ASSERT_EQ(OkStatus(), reader.Open());
385 Result<ConstByteSpan> result = reader.GetMemoryMappedBlob();
386 ASSERT_TRUE(result.ok());
387 EXPECT_EQ(original_source.size_bytes(), result.value().size_bytes());
388 VerifyFlash(result.value());
389 VerifyFlash(flash_.buffer());
390 EXPECT_EQ(OkStatus(), reader.Close());
391}
392
Armando Montanez28ad6f42021-08-30 16:23:57 -0700393TEST_F(BlobStoreTest, FileName) {
394 InitSourceBufferToRandom(0x8675309);
395 WriteTestBlock();
396 constexpr std::string_view kFileName("my_file_1.bin");
Armando Montanez28ad6f42021-08-30 16:23:57 -0700397 std::array<std::byte, 64> tmp_buffer = {};
398 static_assert(kFileName.size() <= tmp_buffer.size());
Armando Montanez28ad6f42021-08-30 16:23:57 -0700399 kvs::ChecksumCrc16 checksum;
400 constexpr size_t kBufferSize = 256;
Armando Montanez254ec762021-09-27 15:56:48 -0700401 {
402 // Create/init a blob store in a nested scope so it can be re-initialized
403 // later when checking the read.
404 BlobStoreBuffer<kBufferSize> blob(
405 kBlobTitle, partition_, &checksum, kvs::TestKvs(), kBufferSize);
406 EXPECT_EQ(OkStatus(), blob.Init());
407
Armando Montanez0e8aff82021-09-30 13:21:12 -0700408 BlobStore::BlobWriterWithBuffer<kFileName.size()> writer(blob);
Armando Montanez254ec762021-09-27 15:56:48 -0700409
410 EXPECT_EQ(OkStatus(), writer.Open());
411 EXPECT_EQ(OkStatus(), writer.SetFileName(kFileName));
412 EXPECT_EQ(OkStatus(), writer.Write(tmp_buffer));
413 EXPECT_EQ(OkStatus(), writer.Close());
Ewout van Bekkum1d0aa6d2021-09-22 12:38:10 -0700414 EXPECT_EQ(OkStatus(),
415 kvs::TestKvs().acquire()->Get(kBlobTitle, tmp_buffer).status());
Armando Montanez254ec762021-09-27 15:56:48 -0700416 }
417
Armando Montanez28ad6f42021-08-30 16:23:57 -0700418 BlobStoreBuffer<kBufferSize> blob(
419 kBlobTitle, partition_, &checksum, kvs::TestKvs(), kBufferSize);
420 EXPECT_EQ(OkStatus(), blob.Init());
421
Armando Montanez28ad6f42021-08-30 16:23:57 -0700422 // Ensure the file name can be read from a reader.
423 BlobStore::BlobReader reader(blob);
424 ASSERT_EQ(OkStatus(), reader.Open());
425
426 memset(tmp_buffer.data(), 0, tmp_buffer.size());
427 StatusWithSize sws = reader.GetFileName(
428 {reinterpret_cast<char*>(tmp_buffer.data()), tmp_buffer.size()});
429
430 EXPECT_EQ(OkStatus(), sws.status());
431 ASSERT_EQ(kFileName.size(), sws.size());
432 EXPECT_EQ(memcmp(kFileName.data(), tmp_buffer.data(), kFileName.size()), 0);
433}
434
435TEST_F(BlobStoreTest, FileNameUndersizedRead) {
436 InitSourceBufferToRandom(0x8675309);
437 WriteTestBlock();
438 constexpr std::string_view kFileName("my_file_1.bin");
Armando Montanez28ad6f42021-08-30 16:23:57 -0700439 std::array<std::byte, 4> tmp_buffer = {};
440 static_assert(kFileName.size() > tmp_buffer.size());
441
442 kvs::ChecksumCrc16 checksum;
443 constexpr size_t kBufferSize = 256;
444 BlobStoreBuffer<kBufferSize> blob(
445 kBlobTitle, partition_, &checksum, kvs::TestKvs(), kBufferSize);
446 EXPECT_EQ(OkStatus(), blob.Init());
447
Armando Montanez0e8aff82021-09-30 13:21:12 -0700448 BlobStore::BlobWriterWithBuffer<kFileName.size()> writer(blob);
Armando Montanez28ad6f42021-08-30 16:23:57 -0700449
450 EXPECT_EQ(OkStatus(), writer.Open());
451 EXPECT_EQ(OkStatus(), writer.SetFileName(kFileName));
452 EXPECT_EQ(OkStatus(),
453 writer.Write(std::as_bytes(std::span("some interesting data"))));
454 EXPECT_EQ(OkStatus(), writer.Close());
455
456 // Ensure the file name can be read from a reader.
457 BlobStore::BlobReader reader(blob);
458 ASSERT_EQ(OkStatus(), reader.Open());
459
460 StatusWithSize sws = reader.GetFileName(
461 {reinterpret_cast<char*>(tmp_buffer.data()), tmp_buffer.size()});
462 EXPECT_EQ(Status::ResourceExhausted(), sws.status());
463 ASSERT_EQ(tmp_buffer.size(), sws.size());
464 EXPECT_EQ(memcmp(kFileName.data(), tmp_buffer.data(), sws.size()), 0);
465}
466
467TEST_F(BlobStoreTest, FileNameUndersizedSet) {
468 InitSourceBufferToRandom(0x8675309);
469 WriteTestBlock();
470 constexpr std::string_view kFileName("my_file_1.bin");
Armando Montanez28ad6f42021-08-30 16:23:57 -0700471
472 kvs::ChecksumCrc16 checksum;
473 constexpr size_t kBufferSize = 256;
474 BlobStoreBuffer<kBufferSize> blob(
475 kBlobTitle, partition_, &checksum, kvs::TestKvs(), kBufferSize);
476 EXPECT_EQ(OkStatus(), blob.Init());
477
Armando Montanez0e8aff82021-09-30 13:21:12 -0700478 BlobStore::BlobWriterWithBuffer<2> writer(blob);
Armando Montanez28ad6f42021-08-30 16:23:57 -0700479
480 EXPECT_EQ(OkStatus(), writer.Open());
481 EXPECT_EQ(Status::ResourceExhausted(), writer.SetFileName(kFileName));
482 EXPECT_EQ(OkStatus(), writer.Close());
483}
484
485TEST_F(BlobStoreTest, FileNameInvalidation) {
486 InitSourceBufferToRandom(0x8675309);
487 WriteTestBlock();
488
489 constexpr std::string_view kFileName("sliced_cheese.png");
Armando Montanez28ad6f42021-08-30 16:23:57 -0700490 std::array<std::byte, 64> tmp_buffer = {};
491 static_assert(kFileName.size() <= tmp_buffer.size());
492
493 kvs::ChecksumCrc16 checksum;
494 constexpr size_t kBufferSize = 256;
495 BlobStoreBuffer<kBufferSize> blob(
496 kBlobTitle, partition_, &checksum, kvs::TestKvs(), kBufferSize);
497 EXPECT_EQ(OkStatus(), blob.Init());
498
Armando Montanez0e8aff82021-09-30 13:21:12 -0700499 BlobStore::BlobWriterWithBuffer<kFileName.size()> writer(blob);
Armando Montanez28ad6f42021-08-30 16:23:57 -0700500
501 EXPECT_EQ(OkStatus(), writer.Open());
502 EXPECT_EQ(OkStatus(), writer.SetFileName(kFileName));
503 EXPECT_EQ(OkStatus(), writer.Write(tmp_buffer));
504 EXPECT_EQ(OkStatus(), writer.Discard());
505 EXPECT_EQ(OkStatus(), writer.Write(tmp_buffer));
506 EXPECT_EQ(OkStatus(), writer.Close());
507
508 // Check that the file name was discarded by Discard().
509 memset(tmp_buffer.data(), 0, tmp_buffer.size());
510 BlobStore::BlobReader reader(blob);
511 ASSERT_EQ(OkStatus(), reader.Open());
512 StatusWithSize sws = reader.GetFileName(
513 {reinterpret_cast<char*>(tmp_buffer.data()), tmp_buffer.size()});
514 EXPECT_EQ(Status::NotFound(), sws.status());
515 ASSERT_EQ(0u, sws.size());
516}
517
518TEST_F(BlobStoreTest, NoFileName) {
519 InitSourceBufferToRandom(0x8675309);
520 WriteTestBlock();
521
522 std::array<std::byte, 64> tmp_buffer = {};
523 kvs::ChecksumCrc16 checksum;
524 constexpr size_t kBufferSize = 256;
525 BlobStoreBuffer<kBufferSize> blob(
526 kBlobTitle, partition_, &checksum, kvs::TestKvs(), kBufferSize);
527 EXPECT_EQ(OkStatus(), blob.Init());
528
529 // Ensure blobs with no file names work as expected.
530 BlobStore::BlobReader reader(blob);
531 ASSERT_EQ(OkStatus(), reader.Open());
532
533 StatusWithSize sws = reader.GetFileName(
534 {reinterpret_cast<char*>(tmp_buffer.data()), tmp_buffer.size()});
535 EXPECT_EQ(Status::NotFound(), sws.status());
536 ASSERT_EQ(0u, sws.size());
537}
538
539TEST_F(BlobStoreTest, V1MetadataBackwardsCompatible) {
540 constexpr size_t kWriteSize = 25;
541 WriteTestBlock(kWriteSize);
542
543 kvs::ChecksumCrc16 checksum;
544 constexpr size_t kBufferSize = 16;
545 BlobStoreBuffer<kBufferSize> blob(
546 kBlobTitle, partition_, &checksum, kvs::TestKvs(), kBufferSize);
547 EXPECT_EQ(OkStatus(), blob.Init());
548
549 // Read the written data in the current format.
550 internal::BlobMetadataHeader current_metadata;
Ewout van Bekkum1d0aa6d2021-09-22 12:38:10 -0700551 ASSERT_EQ(OkStatus(),
552 kvs::TestKvs().acquire()->Get(kBlobTitle, &current_metadata));
Armando Montanez28ad6f42021-08-30 16:23:57 -0700553
554 // Re-save only the V1 metadata contents.
Ewout van Bekkum1d0aa6d2021-09-22 12:38:10 -0700555 ASSERT_EQ(
556 OkStatus(),
557 kvs::TestKvs().acquire()->Put(kBlobTitle, current_metadata.v1_metadata));
Armando Montanez28ad6f42021-08-30 16:23:57 -0700558
559 // Ensure the BlobStore's contents aren't invalid.
560 BlobStore::BlobReader reader(blob);
561 ASSERT_EQ(OkStatus(), reader.Open());
562 ASSERT_EQ(kWriteSize, reader.ConservativeReadLimit());
563 ASSERT_EQ(current_metadata.v1_metadata.data_size_bytes,
564 reader.ConservativeReadLimit());
565}
566
David Rogers175851f2020-09-22 16:25:34 -0700567TEST_F(BlobStoreTest, Discard) {
568 InitSourceBufferToRandom(0x8675309);
569 WriteTestBlock();
David Rogers22f7b3e2020-10-07 23:58:11 -0700570 constexpr char blob_title[] = "TestBlobBlock";
571 std::array<std::byte, 64> tmp_buffer = {};
David Rogers175851f2020-09-22 16:25:34 -0700572
573 kvs::ChecksumCrc16 checksum;
David Rogers22f7b3e2020-10-07 23:58:11 -0700574
575 // TODO: Do this test with flash/kvs in the different entry state
576 // combinations.
577
David Rogers1f08acb2020-11-17 23:11:58 -0800578 constexpr size_t kBufferSize = 256;
579 BlobStoreBuffer<kBufferSize> blob(
580 blob_title, partition_, &checksum, kvs::TestKvs(), kBufferSize);
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800581 EXPECT_EQ(OkStatus(), blob.Init());
David Rogers175851f2020-09-22 16:25:34 -0700582
David Rogers2835cf62022-03-10 20:23:20 -0800583 EXPECT_TRUE(blob.HasData());
584
Armando Montanez0e8aff82021-09-30 13:21:12 -0700585 BlobStore::BlobWriterWithBuffer writer(blob);
David Rogers22f7b3e2020-10-07 23:58:11 -0700586
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800587 EXPECT_EQ(OkStatus(), writer.Open());
588 EXPECT_EQ(OkStatus(), writer.Write(tmp_buffer));
David Rogers22f7b3e2020-10-07 23:58:11 -0700589
David Rogers2835cf62022-03-10 20:23:20 -0800590 // Blob should NOT be valid to read, because the write data was only buffered,
591 // and has not been written to flash yet.
592 EXPECT_FALSE(blob.HasData());
593
David Rogers22f7b3e2020-10-07 23:58:11 -0700594 // The write does an implicit erase so there should be no key for this blob.
Wyatt Heplerf276c6b2020-11-11 21:13:38 -0800595 EXPECT_EQ(Status::NotFound(),
Ewout van Bekkum1d0aa6d2021-09-22 12:38:10 -0700596 kvs::TestKvs().acquire()->Get(blob_title, tmp_buffer).status());
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800597 EXPECT_EQ(OkStatus(), writer.Close());
David Rogers22f7b3e2020-10-07 23:58:11 -0700598
David Rogers2835cf62022-03-10 20:23:20 -0800599 EXPECT_TRUE(blob.HasData());
600
Ewout van Bekkum1d0aa6d2021-09-22 12:38:10 -0700601 EXPECT_EQ(OkStatus(),
602 kvs::TestKvs().acquire()->Get(blob_title, tmp_buffer).status());
David Rogers22f7b3e2020-10-07 23:58:11 -0700603
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800604 EXPECT_EQ(OkStatus(), writer.Open());
605 EXPECT_EQ(OkStatus(), writer.Discard());
606 EXPECT_EQ(OkStatus(), writer.Close());
David Rogers22f7b3e2020-10-07 23:58:11 -0700607
David Rogers2835cf62022-03-10 20:23:20 -0800608 EXPECT_FALSE(blob.HasData());
609
Wyatt Heplerf276c6b2020-11-11 21:13:38 -0800610 EXPECT_EQ(Status::NotFound(),
Ewout van Bekkum1d0aa6d2021-09-22 12:38:10 -0700611 kvs::TestKvs().acquire()->Get(blob_title, tmp_buffer).status());
David Rogers175851f2020-09-22 16:25:34 -0700612}
613
David Rogers5aa32ab2020-09-08 14:39:24 -0700614TEST_F(BlobStoreTest, MultipleErase) {
David Rogers1f08acb2020-11-17 23:11:58 -0800615 constexpr size_t kBufferSize = 256;
616 BlobStoreBuffer<kBufferSize> blob(
617 "Blob_OK", partition_, nullptr, kvs::TestKvs(), kBufferSize);
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800618 EXPECT_EQ(OkStatus(), blob.Init());
David Rogers96922572020-08-04 10:24:57 -0700619
Armando Montanez0e8aff82021-09-30 13:21:12 -0700620 BlobStore::BlobWriterWithBuffer writer(blob);
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800621 EXPECT_EQ(OkStatus(), writer.Open());
David Rogers96922572020-08-04 10:24:57 -0700622
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800623 EXPECT_EQ(OkStatus(), writer.Erase());
624 EXPECT_EQ(OkStatus(), writer.Erase());
625 EXPECT_EQ(OkStatus(), writer.Erase());
David Rogers5aa32ab2020-09-08 14:39:24 -0700626}
David Rogers96922572020-08-04 10:24:57 -0700627
David Rogers10395842020-09-16 15:39:35 -0700628TEST_F(BlobStoreTest, OffsetRead) {
629 InitSourceBufferToRandom(0x11309);
630 WriteTestBlock();
631
632 constexpr size_t kOffset = 10;
633 ASSERT_LT(kOffset, kBlobDataSize);
634
635 kvs::ChecksumCrc16 checksum;
636
637 char name[16] = "TestBlobBlock";
David Rogers1f08acb2020-11-17 23:11:58 -0800638 constexpr size_t kBufferSize = 16;
639 BlobStoreBuffer<kBufferSize> blob(
640 name, partition_, &checksum, kvs::TestKvs(), kBufferSize);
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800641 EXPECT_EQ(OkStatus(), blob.Init());
David Rogers10395842020-09-16 15:39:35 -0700642 BlobStore::BlobReader reader(blob);
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800643 ASSERT_EQ(OkStatus(), reader.Open(kOffset));
David Rogers10395842020-09-16 15:39:35 -0700644
David Rogers84e0dec2020-11-24 14:33:18 -0800645 std::array<std::byte, kBlobDataSize - kOffset> read_buffer;
646 ByteSpan read_span = read_buffer;
David Rogers10395842020-09-16 15:39:35 -0700647 ASSERT_EQ(read_span.size_bytes(), reader.ConservativeReadLimit());
648
649 auto result = reader.Read(read_span);
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800650 ASSERT_EQ(result.status(), OkStatus());
651 EXPECT_EQ(OkStatus(), reader.Close());
David Rogers84e0dec2020-11-24 14:33:18 -0800652 VerifyFlash(read_buffer, kOffset);
David Rogers10395842020-09-16 15:39:35 -0700653}
654
Yecheng Zhao4a6deb42021-09-01 15:23:00 -0700655TEST_F(BlobStoreTest, SeekOffsetRead) {
656 InitSourceBufferToRandom(0x11309);
657 WriteTestBlock();
658
659 constexpr size_t kOffset = 10;
660 ASSERT_LT(kOffset, kBlobDataSize);
661
662 kvs::ChecksumCrc16 checksum;
663
664 char name[16] = "TestBlobBlock";
665 constexpr size_t kBufferSize = 16;
666 BlobStoreBuffer<kBufferSize> blob(
667 name, partition_, &checksum, kvs::TestKvs(), kBufferSize);
668 EXPECT_EQ(OkStatus(), blob.Init());
669 BlobStore::BlobReader reader(blob);
670 ASSERT_EQ(OkStatus(), reader.Open());
671 ASSERT_EQ(OkStatus(), reader.Seek(kOffset));
672
673 std::array<std::byte, kBlobDataSize - kOffset> read_buffer;
674 ByteSpan read_span = read_buffer;
675 ASSERT_EQ(read_span.size_bytes(), reader.ConservativeReadLimit());
676
677 auto result = reader.Read(read_span);
678 ASSERT_EQ(result.status(), OkStatus());
679 EXPECT_EQ(OkStatus(), reader.Close());
680 VerifyFlash(read_buffer, kOffset);
681}
682
David Rogers10395842020-09-16 15:39:35 -0700683TEST_F(BlobStoreTest, InvalidReadOffset) {
684 InitSourceBufferToRandom(0x11309);
685 WriteTestBlock();
686
687 constexpr size_t kOffset = kBlobDataSize;
688
689 kvs::ChecksumCrc16 checksum;
690
691 char name[16] = "TestBlobBlock";
David Rogers1f08acb2020-11-17 23:11:58 -0800692 constexpr size_t kBufferSize = 16;
693 BlobStoreBuffer<kBufferSize> blob(
694 name, partition_, &checksum, kvs::TestKvs(), kBufferSize);
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800695 EXPECT_EQ(OkStatus(), blob.Init());
David Rogers10395842020-09-16 15:39:35 -0700696 BlobStore::BlobReader reader(blob);
Wyatt Heplerd78f7c62020-09-28 14:27:32 -0700697 ASSERT_EQ(Status::InvalidArgument(), reader.Open(kOffset));
David Rogers10395842020-09-16 15:39:35 -0700698}
699
Wyatt Hepler3ce31cc2022-01-10 15:47:28 -0800700TEST_F(BlobStoreTest, ReadSeekClosedReader) {
701 InitSourceBufferToRandom(0x11309);
702 WriteTestBlock();
703
704 kvs::ChecksumCrc16 checksum;
705
706 char name[16] = "TestBlobBlock";
707 constexpr size_t kBufferSize = 16;
708 BlobStoreBuffer<kBufferSize> blob(
709 name, partition_, &checksum, kvs::TestKvs(), kBufferSize);
710 EXPECT_EQ(OkStatus(), blob.Init());
711 BlobStore::BlobReader reader(blob);
712 ASSERT_EQ(OkStatus(), reader.Open());
713 ASSERT_EQ(OkStatus(), reader.Close());
714
715 EXPECT_EQ(Status::FailedPrecondition(), reader.Seek(0));
716
717 std::byte read_buffer[32];
718 EXPECT_EQ(Status::FailedPrecondition(), reader.Read(read_buffer).status());
719}
720
Yecheng Zhao4a6deb42021-09-01 15:23:00 -0700721TEST_F(BlobStoreTest, InvalidSeekOffset) {
722 InitSourceBufferToRandom(0x11309);
723 WriteTestBlock();
724
725 constexpr size_t kOffset = kBlobDataSize;
726
727 kvs::ChecksumCrc16 checksum;
728
729 char name[16] = "TestBlobBlock";
730 constexpr size_t kBufferSize = 16;
731 BlobStoreBuffer<kBufferSize> blob(
732 name, partition_, &checksum, kvs::TestKvs(), kBufferSize);
733 EXPECT_EQ(OkStatus(), blob.Init());
734 BlobStore::BlobReader reader(blob);
735 ASSERT_EQ(OkStatus(), reader.Open());
736 ASSERT_EQ(Status::OutOfRange(), reader.Seek(kOffset));
737}
738
David Rogers6b2bbce2022-03-09 17:14:56 -0800739// Write a block to blob and close with part of a write buffer with unflushed
740// data.
741TEST_F(BlobStoreTest, WriteBufferWithRemainderInBuffer) {
742 InitSourceBufferToRandom(0x11309);
743
744 kvs::ChecksumCrc16 checksum;
745 constexpr size_t kBufferSize = 256;
746 BlobStoreBuffer<kBufferSize> blob(
747 "TestBlobBlock", partition_, &checksum, kvs::TestKvs(), kBufferSize);
748 EXPECT_EQ(OkStatus(), blob.Init());
749
750 const size_t write_size_bytes = kBlobDataSize - 10;
751 ConstByteSpan write_data = std::span(source_buffer_).first(write_size_bytes);
752
753 BlobStore::BlobWriterWithBuffer writer(blob);
754 EXPECT_EQ(OkStatus(), writer.Open());
755 ASSERT_EQ(OkStatus(), writer.Write(write_data));
756 EXPECT_EQ(OkStatus(), writer.Close());
757
758 BlobStore::BlobReader reader(blob);
759 ASSERT_EQ(OkStatus(), reader.Open());
760 EXPECT_EQ(write_size_bytes, reader.ConservativeReadLimit());
761}
762
763// Test reading with a read buffer larger than the available data in the blob.
David Rogers84e0dec2020-11-24 14:33:18 -0800764TEST_F(BlobStoreTest, ReadBufferIsLargerThanData) {
765 InitSourceBufferToRandom(0x57326);
766
767 constexpr size_t kWriteBytes = 64;
768 WriteTestBlock(kWriteBytes);
769
770 kvs::ChecksumCrc16 checksum;
771
772 char name[16] = "TestBlobBlock";
David Rogers1f08acb2020-11-17 23:11:58 -0800773 constexpr size_t kBufferSize = 16;
774 BlobStoreBuffer<kBufferSize> blob(
775 name, partition_, &checksum, kvs::TestKvs(), kBufferSize);
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800776 EXPECT_EQ(OkStatus(), blob.Init());
David Rogers84e0dec2020-11-24 14:33:18 -0800777 BlobStore::BlobReader reader(blob);
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800778 ASSERT_EQ(OkStatus(), reader.Open());
David Rogers84e0dec2020-11-24 14:33:18 -0800779 EXPECT_EQ(kWriteBytes, reader.ConservativeReadLimit());
780
781 std::array<std::byte, kWriteBytes + 10> read_buffer;
782 ByteSpan read_span = read_buffer;
783
784 auto result = reader.Read(read_span);
Wyatt Hepler1b3da3a2021-01-07 13:26:57 -0800785 ASSERT_EQ(result.status(), OkStatus());
786 EXPECT_EQ(OkStatus(), reader.Close());
David Rogers84e0dec2020-11-24 14:33:18 -0800787}
788
David Rogers10395842020-09-16 15:39:35 -0700789TEST_F(BlobStoreTest, ChunkRead1) {
David Rogers5aa32ab2020-09-08 14:39:24 -0700790 InitSourceBufferToRandom(0x8675309);
David Rogers10395842020-09-16 15:39:35 -0700791 WriteTestBlock();
792 ChunkReadTest(1);
David Rogers5aa32ab2020-09-08 14:39:24 -0700793}
David Rogers96922572020-08-04 10:24:57 -0700794
David Rogers10395842020-09-16 15:39:35 -0700795TEST_F(BlobStoreTest, ChunkRead3) {
David Rogers5aa32ab2020-09-08 14:39:24 -0700796 InitSourceBufferToFill(0);
David Rogers10395842020-09-16 15:39:35 -0700797 WriteTestBlock();
798 ChunkReadTest(3);
David Rogers5aa32ab2020-09-08 14:39:24 -0700799}
David Rogers96922572020-08-04 10:24:57 -0700800
David Rogers10395842020-09-16 15:39:35 -0700801TEST_F(BlobStoreTest, ChunkRead4) {
David Rogers5aa32ab2020-09-08 14:39:24 -0700802 InitSourceBufferToFill(1);
David Rogers10395842020-09-16 15:39:35 -0700803 WriteTestBlock();
804 ChunkReadTest(4);
David Rogers5aa32ab2020-09-08 14:39:24 -0700805}
806
David Rogers10395842020-09-16 15:39:35 -0700807TEST_F(BlobStoreTest, ChunkRead5) {
David Rogers5aa32ab2020-09-08 14:39:24 -0700808 InitSourceBufferToFill(0xff);
David Rogers10395842020-09-16 15:39:35 -0700809 WriteTestBlock();
810 ChunkReadTest(5);
David Rogers5aa32ab2020-09-08 14:39:24 -0700811}
812
David Rogers10395842020-09-16 15:39:35 -0700813TEST_F(BlobStoreTest, ChunkRead16) {
David Rogers5aa32ab2020-09-08 14:39:24 -0700814 InitSourceBufferToRandom(0x86);
David Rogers10395842020-09-16 15:39:35 -0700815 WriteTestBlock();
816 ChunkReadTest(16);
David Rogers5aa32ab2020-09-08 14:39:24 -0700817}
818
David Rogers10395842020-09-16 15:39:35 -0700819TEST_F(BlobStoreTest, ChunkRead64) {
David Rogers5aa32ab2020-09-08 14:39:24 -0700820 InitSourceBufferToRandom(0x9);
David Rogers10395842020-09-16 15:39:35 -0700821 WriteTestBlock();
822 ChunkReadTest(64);
David Rogers5aa32ab2020-09-08 14:39:24 -0700823}
824
David Rogers10395842020-09-16 15:39:35 -0700825TEST_F(BlobStoreTest, ChunkReadFull) {
826 InitSourceBufferToRandom(0x9);
827 WriteTestBlock();
828 ChunkReadTest(kBlobDataSize);
David Rogers96922572020-08-04 10:24:57 -0700829}
830
David Rogers22f7b3e2020-10-07 23:58:11 -0700831TEST_F(BlobStoreTest, PartialBufferThenClose) {
832 // Do write of only a partial chunk, which will only have bytes in buffer
833 // (none written to flash) at close.
834 size_t data_bytes = 12;
835 InitSourceBufferToRandom(0x111, data_bytes);
836 WriteTestBlock(data_bytes);
David Rogers5aa32ab2020-09-08 14:39:24 -0700837
David Rogers22f7b3e2020-10-07 23:58:11 -0700838 // Do write with several full chunks and then some partial.
839 data_bytes = 158;
840 InitSourceBufferToRandom(0x3222, data_bytes);
841}
David Rogers5aa32ab2020-09-08 14:39:24 -0700842
David Rogers22f7b3e2020-10-07 23:58:11 -0700843// Test to do write/close, write/close multiple times.
844TEST_F(BlobStoreTest, MultipleWrites) {
845 InitSourceBufferToRandom(0x1121);
846 WriteTestBlock();
847 InitSourceBufferToRandom(0x515);
848 WriteTestBlock();
849 InitSourceBufferToRandom(0x4321);
850 WriteTestBlock();
851}
David Rogers5aa32ab2020-09-08 14:39:24 -0700852
David Rogers96922572020-08-04 10:24:57 -0700853} // namespace
854} // namespace pw::blob_store