#pragma once #include "create_action_map.hpp" #include "data_mock.hpp" #include "firmware_handler.hpp" #include "flags.hpp" #include "image_mock.hpp" #include "triggerable_mock.hpp" #include "util.hpp" #include #include #include #include #include #include namespace ipmi_flash { namespace { using ::testing::Return; class IpmiOnlyFirmwareStaticTest : public ::testing::Test { protected: void SetUp() override { /* Unfortunately, since the FirmwareHandler object ends up owning the * handlers, we can't just share handlers. */ std::unique_ptr image = std::make_unique(); hashImageMock = reinterpret_cast(image.get()); blobs.emplace_back(hashBlobId, std::move(image)); image = std::make_unique(); imageMock2 = reinterpret_cast(image.get()); blobs.emplace_back(staticLayoutBlobId, std::move(image)); std::unique_ptr prepareMock = std::make_unique(); prepareMockPtr = reinterpret_cast(prepareMock.get()); std::unique_ptr verifyMock = std::make_unique(); verifyMockPtr = reinterpret_cast(verifyMock.get()); std::unique_ptr updateMock = std::make_unique(); updateMockPtr = reinterpret_cast(updateMock.get()); std::unique_ptr actionPack = std::make_unique(); actionPack->preparation = std::move(prepareMock); actionPack->verification = std::move(verifyMock); actionPack->update = std::move(updateMock); ActionMap packs; packs[staticLayoutBlobId] = std::move(actionPack); std::vector data; data.emplace_back(FirmwareFlags::UpdateFlags::ipmi, nullptr); handler = FirmwareBlobHandler::CreateFirmwareBlobHandler( std::move(blobs), std::move(data), std::move(packs)); } void expectedState(FirmwareBlobHandler::UpdateState state) { auto realHandler = dynamic_cast(handler.get()); EXPECT_EQ(state, realHandler->getCurrentState()); } void openToInProgress(const std::string& blobId) { if (blobId == hashBlobId) { EXPECT_CALL(*hashImageMock, open(blobId, std::ios::out)) .WillOnce(Return(true)); } else { EXPECT_CALL(*imageMock2, open(blobId, std::ios::out)) .WillOnce(Return(true)); } if (blobId != hashBlobId) { EXPECT_CALL(*prepareMockPtr, trigger()).WillOnce(Return(true)); } EXPECT_TRUE(handler->open(session, flags, blobId)); expectedState(FirmwareBlobHandler::UpdateState::uploadInProgress); } void getToVerificationPending(const std::string& blobId) { openToInProgress(blobId); if (blobId == hashBlobId) { EXPECT_CALL(*hashImageMock, close()).WillRepeatedly(Return()); } else { EXPECT_CALL(*imageMock2, close()).WillRepeatedly(Return()); } handler->close(session); expectedState(FirmwareBlobHandler::UpdateState::verificationPending); } void getToVerificationStarted(const std::string& blobId) { getToVerificationPending(blobId); EXPECT_TRUE(handler->open(session, flags, verifyBlobId)); EXPECT_CALL(*verifyMockPtr, trigger()).WillOnce(Return(true)); EXPECT_TRUE(handler->commit(session, {})); expectedState(FirmwareBlobHandler::UpdateState::verificationStarted); } void getToVerificationStartedWitHashBlob() { /* Open both static and hash to check for activeHashBlobId. */ getToVerificationPending(staticLayoutBlobId); openToInProgress(hashBlobId); EXPECT_CALL(*hashImageMock, close()).WillRepeatedly(Return()); handler->close(session); expectedState(FirmwareBlobHandler::UpdateState::verificationPending); /* Now the hash is active AND the static image is active. */ EXPECT_TRUE(handler->open(session, flags, verifyBlobId)); EXPECT_CALL(*verifyMockPtr, trigger()).WillOnce(Return(true)); EXPECT_TRUE(handler->commit(session, {})); expectedState(FirmwareBlobHandler::UpdateState::verificationStarted); } void getToVerificationCompleted(ActionStatus checkResponse) { getToVerificationStarted(staticLayoutBlobId); EXPECT_CALL(*verifyMockPtr, status()).WillOnce(Return(checkResponse)); blobs::BlobMeta meta; EXPECT_TRUE(handler->stat(session, &meta)); expectedState(FirmwareBlobHandler::UpdateState::verificationCompleted); } void getToUpdatePending() { getToVerificationCompleted(ActionStatus::success); handler->close(session); expectedState(FirmwareBlobHandler::UpdateState::updatePending); } void getToUpdateStarted() { getToUpdatePending(); EXPECT_TRUE(handler->open(session, flags, updateBlobId)); EXPECT_CALL(*updateMockPtr, trigger()).WillOnce(Return(true)); EXPECT_TRUE(handler->commit(session, {})); expectedState(FirmwareBlobHandler::UpdateState::updateStarted); } void getToUpdateCompleted(ActionStatus result) { getToUpdateStarted(); EXPECT_CALL(*updateMockPtr, status()).WillOnce(Return(result)); blobs::BlobMeta meta; EXPECT_TRUE(handler->stat(session, &meta)); expectedState(FirmwareBlobHandler::UpdateState::updateCompleted); } ImageHandlerMock *hashImageMock, *imageMock2; std::vector blobs; std::unique_ptr handler; TriggerMock* prepareMockPtr; TriggerMock* verifyMockPtr; TriggerMock* updateMockPtr; std::uint16_t session = 1; std::uint16_t flags = static_cast(blobs::OpenFlags::write) | FirmwareFlags::UpdateFlags::ipmi; blobs::BlobMeta expectedIdleMeta = {0xff00, 0, {}}; std::vector startingBlobs = {staticLayoutBlobId, hashBlobId}; }; class IpmiOnlyFirmwareTest : public ::testing::Test { protected: ImageHandlerMock *hashImageMock, *imageMock; std::vector blobs; std::unique_ptr handler; void SetUp() override { std::unique_ptr image = std::make_unique(); hashImageMock = reinterpret_cast(image.get()); blobs.emplace_back(hashBlobId, std::move(image)); image = std::make_unique(); imageMock = reinterpret_cast(image.get()); blobs.emplace_back("asdf", std::move(image)); std::vector data; data.emplace_back(FirmwareFlags::UpdateFlags::ipmi, nullptr); handler = FirmwareBlobHandler::CreateFirmwareBlobHandler( std::move(blobs), std::move(data), CreateActionMap("asdf")); } }; class FakeLpcFirmwareTest : public ::testing::Test { protected: DataHandlerMock* dataMock; ImageHandlerMock *hashImageMock, *imageMock; std::vector blobs; std::unique_ptr handler; void SetUp() override { std::unique_ptr image = std::make_unique(); hashImageMock = reinterpret_cast(image.get()); blobs.emplace_back(hashBlobId, std::move(image)); image = std::make_unique(); imageMock = reinterpret_cast(image.get()); blobs.emplace_back("asdf", std::move(image)); auto dataMockInstance = std::make_unique(); dataMock = dataMockInstance.get(); std::vector data; data.emplace_back(FirmwareFlags::UpdateFlags::ipmi, nullptr); data.emplace_back(FirmwareFlags::UpdateFlags::lpc, std::move(dataMockInstance)); handler = FirmwareBlobHandler::CreateFirmwareBlobHandler( std::move(blobs), std::move(data), CreateActionMap("asdf")); } }; } // namespace } // namespace ipmi_flash