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