1 #pragma once 2 3 #include "data_mock.hpp" 4 #include "firmware_handler.hpp" 5 #include "flags.hpp" 6 #include "image_mock.hpp" 7 #include "triggerable_mock.hpp" 8 #include "util.hpp" 9 10 #include <memory> 11 #include <string> 12 #include <unordered_map> 13 #include <vector> 14 15 #include <gmock/gmock.h> 16 #include <gtest/gtest.h> 17 18 namespace ipmi_flash 19 { 20 namespace 21 { 22 23 using ::testing::Return; 24 25 class IpmiOnlyFirmwareStaticTest : public ::testing::Test 26 { 27 protected: 28 void SetUp() override 29 { 30 /* Unfortunately, since the FirmwareHandler object ends up owning the 31 * handlers, we can't just share handlers. 32 */ 33 std::unique_ptr<ImageHandlerInterface> image = 34 std::make_unique<ImageHandlerMock>(); 35 hashImageMock = reinterpret_cast<ImageHandlerMock*>(image.get()); 36 blobs.emplace_back(hashBlobId, std::move(image)); 37 38 image = std::make_unique<ImageHandlerMock>(); 39 imageMock2 = reinterpret_cast<ImageHandlerMock*>(image.get()); 40 blobs.emplace_back(staticLayoutBlobId, std::move(image)); 41 42 std::unique_ptr<TriggerableActionInterface> prepareMock = 43 std::make_unique<TriggerMock>(); 44 prepareMockPtr = reinterpret_cast<TriggerMock*>(prepareMock.get()); 45 46 std::unique_ptr<TriggerableActionInterface> verifyMock = 47 std::make_unique<TriggerMock>(); 48 verifyMockPtr = reinterpret_cast<TriggerMock*>(verifyMock.get()); 49 50 std::unique_ptr<TriggerableActionInterface> updateMock = 51 std::make_unique<TriggerMock>(); 52 updateMockPtr = reinterpret_cast<TriggerMock*>(updateMock.get()); 53 54 std::unique_ptr<ActionPack> actionPack = std::make_unique<ActionPack>(); 55 actionPack->preparation = std::move(prepareMock); 56 actionPack->verification = std::move(verifyMock); 57 actionPack->update = std::move(updateMock); 58 59 ActionMap packs; 60 packs[staticLayoutBlobId] = std::move(actionPack); 61 62 std::vector<DataHandlerPack> data; 63 data.emplace_back(FirmwareFlags::UpdateFlags::ipmi, nullptr); 64 65 handler = FirmwareBlobHandler::CreateFirmwareBlobHandler( 66 std::move(blobs), std::move(data), std::move(packs)); 67 } 68 69 void expectedState(FirmwareBlobHandler::UpdateState state) 70 { 71 auto realHandler = dynamic_cast<FirmwareBlobHandler*>(handler.get()); 72 EXPECT_EQ(state, realHandler->getCurrentState()); 73 } 74 75 void openToInProgress(const std::string& blobId) 76 { 77 if (blobId == hashBlobId) 78 { 79 EXPECT_CALL(*hashImageMock, open(blobId)).WillOnce(Return(true)); 80 } 81 else 82 { 83 EXPECT_CALL(*imageMock2, open(blobId)).WillOnce(Return(true)); 84 } 85 86 if (blobId != hashBlobId) 87 { 88 EXPECT_CALL(*prepareMockPtr, trigger()).WillOnce(Return(true)); 89 } 90 EXPECT_TRUE(handler->open(session, flags, blobId)); 91 expectedState(FirmwareBlobHandler::UpdateState::uploadInProgress); 92 } 93 94 void getToVerificationPending(const std::string& blobId) 95 { 96 openToInProgress(blobId); 97 98 if (blobId == hashBlobId) 99 { 100 EXPECT_CALL(*hashImageMock, close()).WillRepeatedly(Return()); 101 } 102 else 103 { 104 EXPECT_CALL(*imageMock2, close()).WillRepeatedly(Return()); 105 } 106 handler->close(session); 107 expectedState(FirmwareBlobHandler::UpdateState::verificationPending); 108 } 109 110 void getToVerificationStarted(const std::string& blobId) 111 { 112 getToVerificationPending(blobId); 113 114 EXPECT_TRUE(handler->open(session, flags, verifyBlobId)); 115 EXPECT_CALL(*verifyMockPtr, trigger()).WillOnce(Return(true)); 116 117 EXPECT_TRUE(handler->commit(session, {})); 118 expectedState(FirmwareBlobHandler::UpdateState::verificationStarted); 119 } 120 121 void getToVerificationStartedWitHashBlob() 122 { 123 /* Open both static and hash to check for activeHashBlobId. */ 124 getToVerificationPending(staticLayoutBlobId); 125 126 openToInProgress(hashBlobId); 127 EXPECT_CALL(*hashImageMock, close()).WillRepeatedly(Return()); 128 handler->close(session); 129 expectedState(FirmwareBlobHandler::UpdateState::verificationPending); 130 131 /* Now the hash is active AND the static image is active. */ 132 EXPECT_TRUE(handler->open(session, flags, verifyBlobId)); 133 EXPECT_CALL(*verifyMockPtr, trigger()).WillOnce(Return(true)); 134 135 EXPECT_TRUE(handler->commit(session, {})); 136 expectedState(FirmwareBlobHandler::UpdateState::verificationStarted); 137 } 138 139 void getToVerificationCompleted(ActionStatus checkResponse) 140 { 141 getToVerificationStarted(staticLayoutBlobId); 142 143 EXPECT_CALL(*verifyMockPtr, status()).WillOnce(Return(checkResponse)); 144 blobs::BlobMeta meta; 145 EXPECT_TRUE(handler->stat(session, &meta)); 146 expectedState(FirmwareBlobHandler::UpdateState::verificationCompleted); 147 } 148 149 void getToUpdatePending() 150 { 151 getToVerificationCompleted(ActionStatus::success); 152 153 handler->close(session); 154 expectedState(FirmwareBlobHandler::UpdateState::updatePending); 155 } 156 157 void getToUpdateStarted() 158 { 159 getToUpdatePending(); 160 EXPECT_TRUE(handler->open(session, flags, updateBlobId)); 161 162 EXPECT_CALL(*updateMockPtr, trigger()).WillOnce(Return(true)); 163 EXPECT_TRUE(handler->commit(session, {})); 164 expectedState(FirmwareBlobHandler::UpdateState::updateStarted); 165 } 166 167 void getToUpdateCompleted(ActionStatus result) 168 { 169 getToUpdateStarted(); 170 EXPECT_CALL(*updateMockPtr, status()).WillOnce(Return(result)); 171 172 blobs::BlobMeta meta; 173 EXPECT_TRUE(handler->stat(session, &meta)); 174 expectedState(FirmwareBlobHandler::UpdateState::updateCompleted); 175 } 176 177 ImageHandlerMock *hashImageMock, *imageMock2; 178 179 std::vector<HandlerPack> blobs; 180 181 std::unique_ptr<blobs::GenericBlobInterface> handler; 182 183 TriggerMock* prepareMockPtr; 184 TriggerMock* verifyMockPtr; 185 TriggerMock* updateMockPtr; 186 187 std::uint16_t session = 1; 188 std::uint16_t flags = 189 blobs::OpenFlags::write | FirmwareFlags::UpdateFlags::ipmi; 190 191 blobs::BlobMeta expectedIdleMeta = {0xff00, 0, {}}; 192 193 std::vector<std::string> startingBlobs = {staticLayoutBlobId, hashBlobId}; 194 }; 195 196 class IpmiOnlyFirmwareTest : public ::testing::Test 197 { 198 protected: 199 ImageHandlerMock *hashImageMock, *imageMock; 200 std::vector<HandlerPack> blobs; 201 std::unique_ptr<blobs::GenericBlobInterface> handler; 202 203 void SetUp() override 204 { 205 std::unique_ptr<ImageHandlerInterface> image = 206 std::make_unique<ImageHandlerMock>(); 207 hashImageMock = reinterpret_cast<ImageHandlerMock*>(image.get()); 208 blobs.emplace_back(hashBlobId, std::move(image)); 209 210 image = std::make_unique<ImageHandlerMock>(); 211 imageMock = reinterpret_cast<ImageHandlerMock*>(image.get()); 212 blobs.emplace_back("asdf", std::move(image)); 213 214 std::vector<DataHandlerPack> data; 215 data.emplace_back(FirmwareFlags::UpdateFlags::ipmi, nullptr); 216 217 handler = FirmwareBlobHandler::CreateFirmwareBlobHandler( 218 std::move(blobs), std::move(data), CreateActionMap("asdf")); 219 } 220 }; 221 222 class FakeLpcFirmwareTest : public ::testing::Test 223 { 224 protected: 225 DataHandlerMock* dataMock; 226 ImageHandlerMock *hashImageMock, *imageMock; 227 std::vector<HandlerPack> blobs; 228 std::unique_ptr<blobs::GenericBlobInterface> handler; 229 230 void SetUp() override 231 { 232 std::unique_ptr<ImageHandlerInterface> image = 233 std::make_unique<ImageHandlerMock>(); 234 hashImageMock = reinterpret_cast<ImageHandlerMock*>(image.get()); 235 blobs.emplace_back(hashBlobId, std::move(image)); 236 237 image = std::make_unique<ImageHandlerMock>(); 238 imageMock = reinterpret_cast<ImageHandlerMock*>(image.get()); 239 blobs.emplace_back("asdf", std::move(image)); 240 241 auto dataMockInstance = std::make_unique<DataHandlerMock>(); 242 dataMock = dataMockInstance.get(); 243 244 std::vector<DataHandlerPack> data; 245 data.emplace_back(FirmwareFlags::UpdateFlags::ipmi, nullptr); 246 data.emplace_back(FirmwareFlags::UpdateFlags::lpc, 247 std::move(dataMockInstance)); 248 handler = FirmwareBlobHandler::CreateFirmwareBlobHandler( 249 std::move(blobs), std::move(data), CreateActionMap("asdf")); 250 } 251 }; 252 253 } // namespace 254 } // namespace ipmi_flash 255