/* The goal of these tests is to verify that once a host-client has started the * process with one blob bundle, they cannot pivot to upload data to another. * * This prevent someone from starting to upload a BMC firmware, and then midway * through start uploading a BIOS image. */ #include "firmware_handler.hpp" #include "flags.hpp" #include "image_mock.hpp" #include "status.hpp" #include "triggerable_mock.hpp" #include "util.hpp" #include #include #include #include #include namespace ipmi_flash { namespace { using ::testing::Return; class IpmiOnlyTwoFirmwaresTest : public ::testing::Test { protected: 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(); staticImageMock = reinterpret_cast(image.get()); blobs.emplace_back(staticLayoutBlobId, std::move(image)); image = std::make_unique(); biosImageMock = reinterpret_cast(image.get()); blobs.emplace_back(biosBlobId, std::move(image)); std::unique_ptr bmcPrepareMock = std::make_unique(); bmcPrepareMockPtr = reinterpret_cast(bmcPrepareMock.get()); std::unique_ptr bmcVerifyMock = std::make_unique(); bmcVerifyMockPtr = reinterpret_cast(bmcVerifyMock.get()); std::unique_ptr bmcUpdateMock = std::make_unique(); bmcUpdateMockPtr = reinterpret_cast(bmcUpdateMock.get()); std::unique_ptr biosPrepareMock = std::make_unique(); biosPrepareMockPtr = reinterpret_cast(biosPrepareMock.get()); std::unique_ptr biosVerifyMock = std::make_unique(); biosVerifyMockPtr = reinterpret_cast(biosVerifyMock.get()); std::unique_ptr biosUpdateMock = std::make_unique(); biosUpdateMockPtr = reinterpret_cast(biosUpdateMock.get()); ActionMap packs; std::unique_ptr bmcPack = std::make_unique(); bmcPack->preparation = std::move(bmcPrepareMock); bmcPack->verification = std::move(bmcVerifyMock); bmcPack->update = std::move(bmcUpdateMock); std::unique_ptr biosPack = std::make_unique(); biosPack->preparation = std::move(biosPrepareMock); biosPack->verification = std::move(biosVerifyMock); biosPack->update = std::move(biosUpdateMock); packs[staticLayoutBlobId] = std::move(bmcPack); packs[biosBlobId] = std::move(biosPack); 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()); } ImageHandlerMock *hashImageMock, *staticImageMock, *biosImageMock; std::vector blobs; std::unique_ptr handler; TriggerMock *bmcPrepareMockPtr, *bmcVerifyMockPtr, *bmcUpdateMockPtr; TriggerMock *biosPrepareMockPtr, *biosVerifyMockPtr, *biosUpdateMockPtr; std::uint16_t session = 1; std::uint16_t flags = static_cast(blobs::OpenFlags::write) | FirmwareFlags::UpdateFlags::ipmi; }; TEST_F(IpmiOnlyTwoFirmwaresTest, OpeningBiosAfterBlobFails) { /* You can only have one file open at a time, and the first firmware file * you open locks it down */ EXPECT_CALL(*staticImageMock, open(staticLayoutBlobId, std::ios::out)) .WillOnce(Return(true)); EXPECT_CALL(*bmcPrepareMockPtr, trigger()).WillOnce(Return(true)); EXPECT_TRUE(handler->open(session, flags, staticLayoutBlobId)); expectedState(FirmwareBlobHandler::UpdateState::uploadInProgress); EXPECT_CALL(*staticImageMock, close()).WillOnce(Return()); handler->close(session); expectedState(FirmwareBlobHandler::UpdateState::verificationPending); EXPECT_CALL(*biosImageMock, open(biosBlobId, std::ios::out)).Times(0); EXPECT_FALSE(handler->open(session, flags, biosBlobId)); } TEST_F(IpmiOnlyTwoFirmwaresTest, OpeningHashBeforeBiosSucceeds) { /* Opening the hash blob does nothing special in this regard. */ EXPECT_CALL(*hashImageMock, open(hashBlobId, std::ios::out)) .WillOnce(Return(true)); EXPECT_TRUE(handler->open(session, flags, hashBlobId)); expectedState(FirmwareBlobHandler::UpdateState::uploadInProgress); EXPECT_CALL(*hashImageMock, close()).WillOnce(Return()); handler->close(session); expectedState(FirmwareBlobHandler::UpdateState::verificationPending); ASSERT_FALSE(handler->canHandleBlob(verifyBlobId)); EXPECT_CALL(*biosImageMock, open(biosBlobId, std::ios::out)) .WillOnce(Return(true)); EXPECT_TRUE(handler->open(session, flags, biosBlobId)); expectedState(FirmwareBlobHandler::UpdateState::uploadInProgress); EXPECT_CALL(*biosImageMock, close()).WillOnce(Return()); handler->close(session); } } // namespace } // namespace ipmi_flash