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