Add retry to sendFile handler

In cases where the ipmi interface is interrupted, we want to be able to
recover automatically without having to retrigger it again. For example,
this may happen if the ipminet interface gets reconfigure in the middle
of transfering an image.

The inital goal was to have the retry for ipminet only with and restart
at the remaining data instead of from the beginning. The issue there is
that we needed to restart the ipmi blob session to write again and doing
so will clear out the existing written data. When trying to write to
existing session will caused the update to be stalled and required a
ipmi restart to recover.

Tested:
images is able to be tranfered fully and validated after we interrupted
the ipminet interface in the middle.

Change-Id: Id734f6a92625bc6a1256fea010fb4b068f7bf1d5
Signed-off-by: Willy Tu <wltu@google.com>
diff --git a/tools/test/tools_updater_unittest.cpp b/tools/test/tools_updater_unittest.cpp
index cf6cf50..e04cde8 100644
--- a/tools/test/tools_updater_unittest.cpp
+++ b/tools/test/tools_updater_unittest.cpp
@@ -108,21 +108,47 @@
             ipmi_flash::FirmwareFlags::UpdateFlags::openWrite);
 
     EXPECT_CALL(handlerMock, supportedType())
-        .WillOnce(Return(ipmi_flash::FirmwareFlags::UpdateFlags::lpc));
+        .WillRepeatedly(Return(ipmi_flash::FirmwareFlags::UpdateFlags::lpc));
 
     EXPECT_CALL(blobMock, openBlob(ipmi_flash::staticLayoutBlobId, supported))
-        .WillOnce(Return(session));
+        .WillRepeatedly(Return(session));
 
     EXPECT_CALL(handlerMock, sendContents(firmwareImage, session))
-        .WillOnce(Return(false));
+        .WillRepeatedly(Return(false));
 
-    EXPECT_CALL(blobMock, closeBlob(session)).Times(1);
+    EXPECT_CALL(blobMock, closeBlob(session)).Times(3);
 
     EXPECT_THROW(
         updater.sendFile(ipmi_flash::staticLayoutBlobId, firmwareImage),
         ToolException);
 }
 
+TEST_F(UpdateHandlerTest, SendFileHandlerPassWithRetries)
+{
+    std::string firmwareImage = "image.bin";
+
+    std::uint16_t supported =
+        static_cast<std::uint16_t>(
+            ipmi_flash::FirmwareFlags::UpdateFlags::lpc) |
+        static_cast<std::uint16_t>(
+            ipmi_flash::FirmwareFlags::UpdateFlags::openWrite);
+
+    EXPECT_CALL(handlerMock, supportedType())
+        .WillRepeatedly(Return(ipmi_flash::FirmwareFlags::UpdateFlags::lpc));
+
+    EXPECT_CALL(blobMock, openBlob(ipmi_flash::staticLayoutBlobId, supported))
+        .WillRepeatedly(Return(session));
+
+    EXPECT_CALL(handlerMock, sendContents(firmwareImage, session))
+        .WillOnce(Return(false))
+        .WillOnce(Return(false))
+        .WillOnce(Return(true));
+
+    EXPECT_CALL(blobMock, closeBlob(session)).Times(3);
+
+    updater.sendFile(ipmi_flash::staticLayoutBlobId, firmwareImage);
+}
+
 TEST_F(UpdateHandlerTest, VerifyFileHandleReturnsTrueOnSuccess)
 {
     EXPECT_CALL(blobMock, openBlob(ipmi_flash::verifyBlobId, _))