binarystore: Implement open/close
Opening a blob will either have read flag for read only access, or
read|write flag for read/write access. When opening a supported path if
the blob doesn't exist yet, the handler will create an empty blob.
Signed-off-by: Kun Yi <kunyi@google.com>
Change-Id: I3d2c5b761227b77cda8bbc6fa66515e9921c066c
diff --git a/binarystore.cpp b/binarystore.cpp
index aa9c0dc..092a069 100644
--- a/binarystore.cpp
+++ b/binarystore.cpp
@@ -1,5 +1,8 @@
#include "binarystore.hpp"
+#include <algorithm>
+#include <blobs-ipmid/blobs.hpp>
+
namespace binstore
{
@@ -32,7 +35,37 @@
bool BinaryStore::openOrCreateBlob(const std::string& blobId, uint16_t flags)
{
- return false;
+ if (!(flags & blobs::OpenFlags::read))
+ {
+ return false;
+ }
+
+ if (currentBlob_ && (currentBlob_->blob_id() != blobId))
+ {
+ /* Already handling a different blob */
+ return false;
+ }
+
+ writable_ = flags & blobs::OpenFlags::write;
+
+ /* Iterate and find if there is an existing blob with this id.
+ * blobsPtr points to a BinaryBlob container with STL-like semantics*/
+ auto blobsPtr = blob_.mutable_blobs();
+ auto blobIt =
+ std::find_if(blobsPtr->begin(), blobsPtr->end(),
+ [&](const auto& b) { return b.blob_id() == blobId; });
+
+ if (blobIt != blobsPtr->end())
+ {
+ currentBlob_ = &(*blobIt);
+ return true;
+ }
+
+ /* Otherwise, create the blob and append it */
+ currentBlob_ = blob_.add_blobs();
+ currentBlob_->set_blob_id(blobId);
+
+ return true;
}
bool BinaryStore::deleteBlob(const std::string& blobId)
@@ -58,7 +91,9 @@
bool BinaryStore::close()
{
- return false;
+ currentBlob_ = nullptr;
+ writable_ = false;
+ return true;
}
bool BinaryStore::stat()
diff --git a/binarystore.hpp b/binarystore.hpp
index 7020cff..4091fd4 100644
--- a/binarystore.hpp
+++ b/binarystore.hpp
@@ -98,7 +98,7 @@
BinaryStore(const std::string& baseBlobId, int fd, uint32_t offset,
uint32_t maxSize) :
baseBlobId_(baseBlobId),
- fd_(fd), offset_(offset), maxSize_(maxSize)
+ fd_(fd), offset_(offset), maxSize_(maxSize), currentBlob_(nullptr)
{
}
@@ -141,6 +141,7 @@
uint32_t maxSize_;
binaryblobproto::BinaryBlobBase blob_;
binaryblobproto::BinaryBlob* currentBlob_;
+ bool writable_ = false;
};
} // namespace binstore
diff --git a/binarystore_mock.hpp b/binarystore_mock.hpp
index eae08fe..34bec6a 100644
--- a/binarystore_mock.hpp
+++ b/binarystore_mock.hpp
@@ -21,6 +21,11 @@
.WillByDefault(Invoke(&real_store_, &BinaryStore::getBaseBlobId));
ON_CALL(*this, getBlobIds)
.WillByDefault(Invoke(&real_store_, &BinaryStore::getBlobIds));
+ ON_CALL(*this, openOrCreateBlob)
+ .WillByDefault(
+ Invoke(&real_store_, &BinaryStore::openOrCreateBlob));
+ ON_CALL(*this, close)
+ .WillByDefault(Invoke(&real_store_, &BinaryStore::close));
}
MOCK_CONST_METHOD0(getBaseBlobId, std::string());
MOCK_CONST_METHOD0(getBlobIds, std::vector<std::string>());
diff --git a/test/handler_open_unittest.cpp b/test/handler_open_unittest.cpp
index c3d10aa..5706041 100644
--- a/test/handler_open_unittest.cpp
+++ b/test/handler_open_unittest.cpp
@@ -3,6 +3,7 @@
using ::testing::_;
using ::testing::Return;
using ::testing::StartsWith;
+using ::testing::UnorderedElementsAreArray;
using namespace std::string_literals;
using namespace binstore;
@@ -21,13 +22,13 @@
static inline uint16_t openTestSessionId = 0;
};
-TEST_F(BinaryStoreBlobHandlerOpenTest, FailWhenCannotHandleId)
+TEST_F(BinaryStoreBlobHandlerOpenTest, OpenFailWhenNoBlob)
{
- EXPECT_FALSE(handler.open(openTestSessionId, openTestROFlags,
- openTestInvalidBlobId));
+ EXPECT_FALSE(
+ handler.open(openTestSessionId, openTestROFlags, openTestBlobId));
}
-TEST_F(BinaryStoreBlobHandlerOpenTest, FailWhenStoreOpenReturnsFailure)
+TEST_F(BinaryStoreBlobHandlerOpenTest, OpenFailWhenStoreOpenReturnsFailure)
{
auto store = defaultMockStore(openTestBaseId);
@@ -40,7 +41,7 @@
handler.open(openTestSessionId, openTestROFlags, openTestBlobId));
}
-TEST_F(BinaryStoreBlobHandlerOpenTest, SucceedWhenStoreOpenReturnsTrue)
+TEST_F(BinaryStoreBlobHandlerOpenTest, OpenSucceedWhenStoreOpenReturnsTrue)
{
auto store = defaultMockStore(openTestBaseId);
@@ -53,9 +54,41 @@
handler.open(openTestSessionId, openTestROFlags, openTestBlobId));
}
+TEST_F(BinaryStoreBlobHandlerOpenTest, OpenFailForNonMatchingBasePath)
+{
+ addDefaultStore(openTestBaseId);
+ EXPECT_FALSE(handler.open(openTestSessionId, openTestROFlags,
+ openTestInvalidBlobId));
+}
+
+TEST_F(BinaryStoreBlobHandlerOpenTest, OpenCloseSucceedForValidBlobId)
+{
+ addDefaultStore(openTestBaseId);
+
+ EXPECT_FALSE(handler.close(openTestSessionId)); // Haven't open
+ EXPECT_TRUE(
+ handler.open(openTestSessionId, openTestROFlags, openTestBlobId));
+ EXPECT_TRUE(handler.close(openTestSessionId));
+ EXPECT_FALSE(handler.close(openTestSessionId)); // Already closed
+}
+
+TEST_F(BinaryStoreBlobHandlerOpenTest, OpenSuccessShowsBlobId)
+{
+ addDefaultStore(openTestBaseId);
+
+ EXPECT_TRUE(
+ handler.open(openTestSessionId, openTestROFlags, openTestBlobId));
+ EXPECT_THAT(handler.getBlobIds(),
+ UnorderedElementsAreArray({openTestBaseId, openTestBlobId}));
+}
+
TEST_F(BinaryStoreBlobHandlerOpenTest, CloseFailForInvalidSession)
{
uint16_t invalidSessionId = 1;
+
+ addDefaultStore(openTestBaseId);
+ EXPECT_TRUE(
+ handler.open(openTestSessionId, openTestROFlags, openTestBlobId));
EXPECT_FALSE(handler.close(invalidSessionId));
}