tools/handler: Read the running version
A host tool would read the running firmware version through polling the
version blob state.
Signed-off-by: Jie Yang <jjy@google.com>
Change-Id: I0d68fff6527cd52360abee1cb225a8f228d68392
diff --git a/tools/test/tools_helper_unittest.cpp b/tools/test/tools_helper_unittest.cpp
index 9aac01a..2bee66d 100644
--- a/tools/test/tools_helper_unittest.cpp
+++ b/tools/test/tools_helper_unittest.cpp
@@ -1,6 +1,7 @@
#include "helper.hpp"
#include "status.hpp"
+#include <blobs-ipmid/blobs.hpp>
#include <ipmiblob/test/blob_interface_mock.hpp>
#include <cstdint>
@@ -45,6 +46,65 @@
EXPECT_FALSE(pollStatus(session, &blobMock));
}
+TEST_F(HelperTest, PollReadReadyReturnsAfterSuccess)
+{
+ ipmiblob::StatResponse blobResponse = {};
+ /* the other details of the response are ignored, and should be. */
+ blobResponse.blob_state =
+ blobs::StateFlags::open_read | blobs::StateFlags::committed;
+
+ EXPECT_CALL(blobMock, getStat(TypedEq<std::uint16_t>(session)))
+ .WillOnce(Return(blobResponse));
+
+ EXPECT_TRUE(pollReadReady(session, &blobMock).first);
+}
+
+TEST_F(HelperTest, PollReadReadyReturnsAfterFailure)
+{
+ ipmiblob::StatResponse blobResponse = {};
+ /* the other details of the response are ignored, and should be. */
+ blobResponse.blob_state = blobs::StateFlags::commit_error;
+
+ EXPECT_CALL(blobMock, getStat(TypedEq<std::uint16_t>(session)))
+ .WillOnce(Return(blobResponse));
+
+ EXPECT_FALSE(pollReadReady(session, &blobMock).first);
+}
+
+TEST_F(HelperTest, PollReadReadyReturnsAfterRetrySuccess)
+{
+ ipmiblob::StatResponse blobResponseRunning = {};
+ /* the other details of the response are ignored, and should be. */
+ blobResponseRunning.blob_state = blobs::StateFlags::committing;
+
+ ipmiblob::StatResponse blobResponseReadReady = {};
+ /* the other details of the response are ignored, and should be. */
+ blobResponseReadReady.blob_state = blobs::StateFlags::open_read;
+
+ EXPECT_CALL(blobMock, getStat(TypedEq<std::uint16_t>(session)))
+ .WillOnce(Return(blobResponseRunning))
+ .WillOnce(Return(blobResponseReadReady));
+
+ EXPECT_TRUE(pollReadReady(session, &blobMock).first);
+}
+
+TEST_F(HelperTest, PollReadReadyReturnsAfterRetryFailure)
+{
+ ipmiblob::StatResponse blobResponseRunning = {};
+ /* the other details of the response are ignored, and should be. */
+ blobResponseRunning.blob_state = blobs::StateFlags::committing;
+
+ ipmiblob::StatResponse blobResponseError = {};
+ /* the other details of the response are ignored, and should be. */
+ blobResponseError.blob_state = blobs::StateFlags::commit_error;
+
+ EXPECT_CALL(blobMock, getStat(TypedEq<std::uint16_t>(session)))
+ .WillOnce(Return(blobResponseRunning))
+ .WillOnce(Return(blobResponseError));
+
+ EXPECT_FALSE(pollReadReady(session, &blobMock).first);
+}
+
TEST_F(HelperTest, MemcpyAlignedOneByte)
{
const char source = 'a';
diff --git a/tools/test/tools_updater_unittest.cpp b/tools/test/tools_updater_unittest.cpp
index bb28ecb..824cec9 100644
--- a/tools/test/tools_updater_unittest.cpp
+++ b/tools/test/tools_updater_unittest.cpp
@@ -6,6 +6,7 @@
#include "updater_mock.hpp"
#include "util.hpp"
+#include <blobs-ipmid/blobs.hpp>
#include <ipmiblob/blob_errors.hpp>
#include <ipmiblob/test/blob_interface_mock.hpp>
@@ -20,6 +21,7 @@
using ::testing::_;
using ::testing::Eq;
+using ::testing::IsEmpty;
using ::testing::Return;
using ::testing::Throw;
using ::testing::TypedEq;
@@ -172,6 +174,64 @@
ToolException);
}
+TEST_F(UpdateHandlerTest, ReadVerisonReturnExpected)
+{
+ /* It can return as expected, when polling and readBytes succeeds. */
+ EXPECT_CALL(blobMock, openBlob(ipmi_flash::biosVersionBlobId, _))
+ .WillOnce(Return(session));
+ ipmiblob::StatResponse readVersionResponse = {};
+ readVersionResponse.blob_state =
+ blobs::StateFlags::open_read | blobs::StateFlags::committed;
+ readVersionResponse.size = 10;
+ EXPECT_CALL(blobMock, getStat(TypedEq<std::uint16_t>(session)))
+ .WillOnce(Return(readVersionResponse));
+ std::vector<uint8_t> resp = {0x2d, 0xfe};
+ EXPECT_CALL(blobMock, readBytes(session, 0, _)).WillOnce(Return(resp));
+
+ EXPECT_CALL(blobMock, closeBlob(session)).WillOnce(Return());
+ EXPECT_EQ(resp, updater.readVersion(ipmi_flash::biosVersionBlobId));
+}
+
+TEST_F(UpdateHandlerTest, ReadVersionExceptionWhenPollingSucceedsReadBytesFails)
+{
+ /* On readBytes, it can except. */
+ EXPECT_CALL(blobMock, openBlob(ipmi_flash::biosVersionBlobId, _))
+ .WillOnce(Return(session));
+ ipmiblob::StatResponse readVersionResponse = {};
+ readVersionResponse.blob_state =
+ blobs::StateFlags::open_read | blobs::StateFlags::committed;
+ readVersionResponse.size = 10;
+ EXPECT_CALL(blobMock, getStat(TypedEq<std::uint16_t>(session)))
+ .WillOnce(Return(readVersionResponse));
+ EXPECT_CALL(blobMock, readBytes(session, 0, _))
+ .WillOnce(Throw(ipmiblob::BlobException("asdf")));
+ EXPECT_CALL(blobMock, closeBlob(session)).WillOnce(Return());
+ EXPECT_THROW(updater.readVersion(ipmi_flash::biosVersionBlobId),
+ ToolException);
+}
+
+TEST_F(UpdateHandlerTest, ReadVersionReturnsEmptyIfPollingFails)
+{
+ /* It can return an empty result, when polling fails. */
+ EXPECT_CALL(blobMock, openBlob(ipmi_flash::biosVersionBlobId, _))
+ .WillOnce(Return(session));
+ ipmiblob::StatResponse readVersionResponse = {};
+ readVersionResponse.blob_state = blobs::StateFlags::commit_error;
+ EXPECT_CALL(blobMock, getStat(TypedEq<std::uint16_t>(session)))
+ .WillOnce(Return(readVersionResponse));
+ EXPECT_CALL(blobMock, closeBlob(session)).WillOnce(Return());
+ EXPECT_THAT(updater.readVersion(ipmi_flash::biosVersionBlobId), IsEmpty());
+}
+
+TEST_F(UpdateHandlerTest, ReadVersionCovertsOpenBlobExceptionToToolException)
+{
+ /* On open, it can except and this is converted to a ToolException. */
+ EXPECT_CALL(blobMock, openBlob(ipmi_flash::biosVersionBlobId, _))
+ .WillOnce(Throw(ipmiblob::BlobException("asdf")));
+ EXPECT_THROW(updater.readVersion(ipmi_flash::biosVersionBlobId),
+ ToolException);
+}
+
TEST_F(UpdateHandlerTest, CleanArtifactsSkipsCleanupIfUnableToOpen)
{
/* It only tries to commit if it's able to open the blob. However, if
diff --git a/tools/test/updater_mock.hpp b/tools/test/updater_mock.hpp
index 9469c62..05527b2 100644
--- a/tools/test/updater_mock.hpp
+++ b/tools/test/updater_mock.hpp
@@ -2,7 +2,9 @@
#include "updater.hpp"
+#include <cstdint>
#include <string>
+#include <vector>
#include <gmock/gmock.h>
@@ -13,6 +15,7 @@
{
public:
MOCK_METHOD1(checkAvailable, bool(const std::string&));
+ MOCK_METHOD1(readVersion, std::vector<uint8_t>(const std::string&));
MOCK_METHOD2(sendFile, void(const std::string&, const std::string&));
MOCK_METHOD2(verifyFile, bool(const std::string&, bool));
MOCK_METHOD0(cleanArtifacts, void());