Implement stat
Implement both session based and path based stat, and properly
set commit state to dirty when new content has not been committed.
Resolves: openbmc/phosphor-ipmi-blobs-binarystore#3
Tested: unit tests pass
Signed-off-by: Kun Yi <kunyi731@gmail.com>
Change-Id: I7c833cf4c7dcb0089db778caa60fc92edceb984e
diff --git a/test/handler_stat_unittest.cpp b/test/handler_stat_unittest.cpp
new file mode 100644
index 0000000..253d02c
--- /dev/null
+++ b/test/handler_stat_unittest.cpp
@@ -0,0 +1,120 @@
+#include "handler_unittest.hpp"
+
+#include <gtest/gtest.h>
+
+using ::testing::_;
+using ::testing::ElementsAre;
+using ::testing::IsEmpty;
+using ::testing::Return;
+using ::testing::StartsWith;
+
+using namespace std::string_literals;
+
+namespace blobs
+{
+
+class BinaryStoreBlobHandlerStatTest : public BinaryStoreBlobHandlerTest
+{
+ protected:
+ BinaryStoreBlobHandlerStatTest()
+ {
+ addDefaultStore(statTestBaseId);
+ }
+
+ static inline std::string statTestBaseId = "/test/"s;
+ static inline std::string statTestBlobId = "/test/blob0"s;
+ static inline std::vector<uint8_t> statTestData = {0, 1, 2, 3};
+ static inline std::vector<uint8_t> statTestDataToOverwrite = {
+ 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14};
+ static inline std::vector<uint8_t> commitMetaUnused;
+
+ static inline uint16_t statTestSessionId = 0;
+ static inline uint16_t statTestNewSessionId = 1;
+ static inline uint32_t statTestOffset = 0;
+
+ void openAndWriteTestData(
+ const std::vector<uint8_t>& testData = statTestData)
+ {
+ uint16_t flags = OpenFlags::read | OpenFlags::write;
+ EXPECT_TRUE(handler.open(statTestSessionId, flags, statTestBlobId));
+ EXPECT_TRUE(handler.write(statTestSessionId, statTestOffset, testData));
+ }
+
+ void commitData()
+ {
+ EXPECT_TRUE(handler.commit(statTestSessionId, commitMetaUnused));
+ }
+};
+
+TEST_F(BinaryStoreBlobHandlerStatTest, InitialStatIsValidQueriedWithBlobId)
+{
+ BlobMeta meta;
+
+ /* Querying stat fails if there is no open session */
+ EXPECT_FALSE(handler.stat(statTestSessionId, &meta));
+ /* However stat completes if queried using blobId. Returning default. */
+ EXPECT_TRUE(handler.stat(statTestBlobId, &meta));
+ EXPECT_EQ(meta.size, 0);
+};
+
+TEST_F(BinaryStoreBlobHandlerStatTest, StatShowsCommittedState)
+{
+ BlobMeta meta;
+ const int testIter = 2;
+
+ openAndWriteTestData();
+ for (int i = 0; i < testIter; ++i)
+ {
+ EXPECT_TRUE(handler.stat(statTestSessionId, &meta));
+ EXPECT_EQ(meta.size, statTestData.size());
+ EXPECT_TRUE(meta.blobState & OpenFlags::read);
+ EXPECT_TRUE(meta.blobState & OpenFlags::write);
+ EXPECT_FALSE(meta.blobState & StateFlags::committed);
+ EXPECT_TRUE(meta.blobState & BinaryStore::CommitState::Dirty);
+ }
+
+ commitData();
+ for (int i = 0; i < testIter; ++i)
+ {
+ EXPECT_TRUE(handler.stat(statTestSessionId, &meta));
+ EXPECT_EQ(meta.size, statTestData.size());
+ EXPECT_TRUE(meta.blobState & OpenFlags::read);
+ EXPECT_TRUE(meta.blobState & OpenFlags::write);
+ EXPECT_TRUE(meta.blobState & StateFlags::committed);
+ EXPECT_TRUE(meta.blobState & BinaryStore::CommitState::Clean);
+ }
+}
+
+TEST_F(BinaryStoreBlobHandlerStatTest, StatChangedWhenOverwriting)
+{
+ BlobMeta meta;
+ const int testIter = 2;
+
+ openAndWriteTestData();
+ commitData();
+ // Overwrite with different data.
+ EXPECT_TRUE(handler.write(statTestSessionId, statTestOffset,
+ statTestDataToOverwrite));
+ for (int i = 0; i < testIter; ++i)
+ {
+ EXPECT_TRUE(handler.stat(statTestSessionId, &meta));
+ EXPECT_EQ(meta.size, statTestDataToOverwrite.size());
+ EXPECT_TRUE(meta.blobState & OpenFlags::read);
+ EXPECT_TRUE(meta.blobState & OpenFlags::write);
+ EXPECT_FALSE(meta.blobState & StateFlags::committed);
+ EXPECT_TRUE(meta.blobState & BinaryStore::CommitState::Dirty);
+ }
+
+ commitData();
+ for (int i = 0; i < testIter; ++i)
+ {
+ EXPECT_TRUE(handler.stat(statTestSessionId, &meta));
+ EXPECT_EQ(meta.size, statTestDataToOverwrite.size());
+ EXPECT_TRUE(meta.blobState & OpenFlags::read);
+ EXPECT_TRUE(meta.blobState & OpenFlags::write);
+ EXPECT_TRUE(meta.blobState & StateFlags::committed);
+ EXPECT_TRUE(meta.blobState & BinaryStore::CommitState::Clean);
+ }
+}
+
+} // namespace blobs