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