pw_blob_store: Add IsOpen for reader and writer

- Add IsOpen method for both reader and writer.
- Remove a DASSERT in DoRead that was incorrectly limiting read buffer
size to available data size.

Change-Id: I12be460c145676167b1223726fc14d5ffc44a5e2
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/26023
Reviewed-by: Ewout van Bekkum <ewout@google.com>
Commit-Queue: David Rogers <davidrogers@google.com>
diff --git a/pw_blob_store/blob_store_test.cc b/pw_blob_store/blob_store_test.cc
index 39666b4..4c1fe3d 100644
--- a/pw_blob_store/blob_store_test.cc
+++ b/pw_blob_store/blob_store_test.cc
@@ -87,8 +87,8 @@
     Result<ConstByteSpan> result = reader.GetMemoryMappedBlob();
     ASSERT_TRUE(result.ok());
     EXPECT_EQ(write_size_bytes, result.value().size_bytes());
-    VerifyFlash(result.value());
-    VerifyFlash(flash_.buffer());
+    VerifyFlash(result.value().first(write_size_bytes));
+    VerifyFlash(flash_.buffer().first(write_size_bytes));
     EXPECT_EQ(Status::OK, reader.Close());
   }
 
@@ -113,9 +113,9 @@
     BlobStore::BlobReader reader(blob);
     ASSERT_EQ(Status::Ok(), reader.Open());
 
-    std::array<std::byte, kBlobDataSize> read_buffer_;
+    std::array<std::byte, kBlobDataSize> read_buffer;
 
-    ByteSpan read_span = read_buffer_;
+    ByteSpan read_span = read_buffer;
     while (read_span.size_bytes() > 0) {
       size_t read_size = std::min(read_span.size_bytes(), read_chunk_size);
 
@@ -130,7 +130,7 @@
     }
     EXPECT_EQ(Status::Ok(), reader.Close());
 
-    VerifyFlash(read_buffer_);
+    VerifyFlash(read_buffer);
   }
 
   void VerifyFlash(ConstByteSpan verify_bytes, size_t offset = 0) {
@@ -162,6 +162,36 @@
   EXPECT_EQ(Status::Ok(), blob.Init());
 }
 
+TEST_F(BlobStoreTest, IsOpen) {
+  BlobStoreBuffer<256> blob("Blob_open", partition_, nullptr, kvs::TestKvs());
+  EXPECT_EQ(Status::Ok(), blob.Init());
+
+  BlobStore::DeferredWriter deferred_writer(blob);
+  EXPECT_EQ(false, deferred_writer.IsOpen());
+  EXPECT_EQ(Status::OK, deferred_writer.Open());
+  EXPECT_EQ(true, deferred_writer.IsOpen());
+  EXPECT_EQ(Status::OK, deferred_writer.Close());
+  EXPECT_EQ(false, deferred_writer.IsOpen());
+
+  BlobStore::BlobWriter writer(blob);
+  EXPECT_EQ(false, writer.IsOpen());
+  EXPECT_EQ(Status::OK, writer.Open());
+  EXPECT_EQ(true, writer.IsOpen());
+
+  // Need to write something, so the blob reader is able to open.
+  std::array<std::byte, 64> tmp_buffer = {};
+  EXPECT_EQ(Status::OK, writer.Write(tmp_buffer));
+  EXPECT_EQ(Status::OK, writer.Close());
+  EXPECT_EQ(false, writer.IsOpen());
+
+  BlobStore::BlobReader reader(blob);
+  EXPECT_EQ(false, reader.IsOpen());
+  ASSERT_EQ(Status::Ok(), reader.Open());
+  EXPECT_EQ(true, reader.IsOpen());
+  EXPECT_EQ(Status::Ok(), reader.Close());
+  EXPECT_EQ(false, reader.IsOpen());
+}
+
 TEST_F(BlobStoreTest, Discard) {
   InitSourceBufferToRandom(0x8675309);
   WriteTestBlock();
@@ -223,14 +253,14 @@
   BlobStore::BlobReader reader(blob);
   ASSERT_EQ(Status::Ok(), reader.Open(kOffset));
 
-  std::array<std::byte, kBlobDataSize - kOffset> read_buffer_;
-  ByteSpan read_span = read_buffer_;
+  std::array<std::byte, kBlobDataSize - kOffset> read_buffer;
+  ByteSpan read_span = read_buffer;
   ASSERT_EQ(read_span.size_bytes(), reader.ConservativeReadLimit());
 
   auto result = reader.Read(read_span);
   ASSERT_EQ(result.status(), Status::Ok());
   EXPECT_EQ(Status::Ok(), reader.Close());
-  VerifyFlash(read_buffer_, kOffset);
+  VerifyFlash(read_buffer, kOffset);
 }
 
 TEST_F(BlobStoreTest, InvalidReadOffset) {
@@ -248,6 +278,30 @@
   ASSERT_EQ(Status::InvalidArgument(), reader.Open(kOffset));
 }
 
+// Test reading with a read buffer larger than the available data in the
+TEST_F(BlobStoreTest, ReadBufferIsLargerThanData) {
+  InitSourceBufferToRandom(0x57326);
+
+  constexpr size_t kWriteBytes = 64;
+  WriteTestBlock(kWriteBytes);
+
+  kvs::ChecksumCrc16 checksum;
+
+  char name[16] = "TestBlobBlock";
+  BlobStoreBuffer<16> blob(name, partition_, &checksum, kvs::TestKvs());
+  EXPECT_EQ(Status::Ok(), blob.Init());
+  BlobStore::BlobReader reader(blob);
+  ASSERT_EQ(Status::Ok(), reader.Open());
+  EXPECT_EQ(kWriteBytes, reader.ConservativeReadLimit());
+
+  std::array<std::byte, kWriteBytes + 10> read_buffer;
+  ByteSpan read_span = read_buffer;
+
+  auto result = reader.Read(read_span);
+  ASSERT_EQ(result.status(), Status::Ok());
+  EXPECT_EQ(Status::Ok(), reader.Close());
+}
+
 TEST_F(BlobStoreTest, ChunkRead1) {
   InitSourceBufferToRandom(0x8675309);
   WriteTestBlock();
diff --git a/pw_blob_store/public/pw_blob_store/blob_store.h b/pw_blob_store/public/pw_blob_store/blob_store.h
index e00eb6f..6603693 100644
--- a/pw_blob_store/public/pw_blob_store/blob_store.h
+++ b/pw_blob_store/public/pw_blob_store/blob_store.h
@@ -93,6 +93,8 @@
       return store_.CloseWrite();
     }
 
+    bool IsOpen() { return open_; }
+
     // Erase the blob partition and reset state for a new blob. Explicit calls
     // to Erase are optional, beginning a write will do any needed Erase.
     // Returns:
@@ -225,6 +227,8 @@
       return store_.CloseRead();
     }
 
+    bool IsOpen() { return open_; }
+
     // Probable (not guaranteed) minimum number of bytes at this time that can
     // be read. Returns zero if, in the current state, Read would return status
     // other than OK. See stream.h for additional details.
@@ -248,7 +252,6 @@
       PW_DASSERT(open_);
       StatusWithSize status = store_.Read(offset_, dest);
       if (status.ok()) {
-        PW_DASSERT(status.size() == dest.size_bytes());
         offset_ += status.size();
       }
       return status;