blob: implement deleteBlob command

Implement the deleteBlob command for the blob handler. Adding a unit
test to go along with it.

Change-Id: I2bbc93a6e78d5311bd2033d6a8b179374777f794
Signed-off-by: Brandon Kim <brandonkim@google.com>
diff --git a/src/ipmiblob/blob_handler.cpp b/src/ipmiblob/blob_handler.cpp
index 40c725d..d93f5c3 100644
--- a/src/ipmiblob/blob_handler.cpp
+++ b/src/ipmiblob/blob_handler.cpp
@@ -334,6 +334,24 @@
     return;
 }
 
+void BlobHandler::deleteBlob(const std::string& id)
+{
+    std::vector<std::uint8_t> name;
+    std::copy(id.begin(), id.end(), std::back_inserter(name));
+    name.push_back(0x00); /* need to add nul-terminator. */
+
+    try
+    {
+        sendIpmiPayload(BlobOEMCommands::bmcBlobDelete, name);
+    }
+    catch (const BlobException& b)
+    {
+        std::fprintf(stderr, "Received failure on delete: %s\n", b.what());
+    }
+
+    return;
+}
+
 std::vector<std::uint8_t> BlobHandler::readBytes(std::uint16_t session,
                                                  std::uint32_t offset,
                                                  std::uint32_t length)
diff --git a/src/ipmiblob/blob_handler.hpp b/src/ipmiblob/blob_handler.hpp
index c57b11d..33634fd 100644
--- a/src/ipmiblob/blob_handler.hpp
+++ b/src/ipmiblob/blob_handler.hpp
@@ -82,6 +82,8 @@
 
     void closeBlob(std::uint16_t session) override;
 
+    void deleteBlob(const std::string& id) override;
+
     /**
      * @throws BlobException.
      */
diff --git a/src/ipmiblob/blob_interface.hpp b/src/ipmiblob/blob_interface.hpp
index fbd8c6a..ca90cdf 100644
--- a/src/ipmiblob/blob_interface.hpp
+++ b/src/ipmiblob/blob_interface.hpp
@@ -114,6 +114,13 @@
     virtual void closeBlob(std::uint16_t session) = 0;
 
     /**
+     * Attempt to delete a blobId.
+     *
+     * @param[in] path - the blobId path.
+     */
+    virtual void deleteBlob(const std::string& id) = 0;
+
+    /**
      * Read bytes from a blob.
      *
      * @param[in] session - the session id.
diff --git a/src/ipmiblob/test/blob_interface_mock.hpp b/src/ipmiblob/test/blob_interface_mock.hpp
index 7fb94c5..f5137d5 100644
--- a/src/ipmiblob/test/blob_interface_mock.hpp
+++ b/src/ipmiblob/test/blob_interface_mock.hpp
@@ -19,6 +19,7 @@
     MOCK_METHOD1(getStat, StatResponse(std::uint16_t));
     MOCK_METHOD2(openBlob, std::uint16_t(const std::string&, std::uint16_t));
     MOCK_METHOD1(closeBlob, void(std::uint16_t));
+    MOCK_METHOD1(deleteBlob, void(const std::string&));
     MOCK_METHOD3(readBytes,
                  std::vector<std::uint8_t>(std::uint16_t, std::uint32_t,
                                            std::uint32_t));
diff --git a/test/tools_blob_unittest.cpp b/test/tools_blob_unittest.cpp
index 3fe7974..fff3a56 100644
--- a/test/tools_blob_unittest.cpp
+++ b/test/tools_blob_unittest.cpp
@@ -449,4 +449,32 @@
     EXPECT_EQ(blob.readBytes(0x0001, 0, 4), expectedBytes);
 }
 
+TEST_F(BlobHandlerTest, deleteBlobSucceeds)
+{
+    /* The delete succeeds. */
+    auto ipmi = CreateIpmiMock();
+    IpmiInterfaceMock* ipmiMock =
+        reinterpret_cast<IpmiInterfaceMock*>(ipmi.get());
+    BlobHandler blob(std::move(ipmi));
+
+    std::vector<std::uint8_t> request = {
+        0xcf, 0xc2,
+        0x00, static_cast<std::uint8_t>(BlobOEMCommands::bmcBlobDelete),
+        0x00, 0x00,
+        'a',  'b',
+        'c',  'd',
+        0x00};
+
+    std::vector<std::uint8_t> resp = {0xcf, 0xc2, 0x00};
+    std::vector<std::uint8_t> reqCrc = {'a', 'b', 'c', 'd', 0x00};
+    EXPECT_CALL(crcMock, generateCrc(ContainerEq(reqCrc)))
+        .WillOnce(Return(0x00));
+
+    EXPECT_CALL(*ipmiMock,
+                sendPacket(ipmiOEMNetFn, ipmiOEMBlobCmd, ContainerEq(request)))
+        .WillOnce(Return(resp));
+
+    blob.deleteBlob("abcd");
+}
+
 } // namespace ipmiblob