xref: /openbmc/phosphor-ipmi-flash/bmc/firmware-handler/test/firmware_unittest.hpp (revision ded66d0f7317f6e43a5301da6c3d9dda80b17250)
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