1ded66d0fSJason Ling /* The goal of these tests is to verify that once a host-client has started the
2ded66d0fSJason Ling * process with one blob bundle, they cannot pivot to upload data to another.
3ded66d0fSJason Ling *
4ded66d0fSJason Ling * This prevent someone from starting to upload a BMC firmware, and then midway
5ded66d0fSJason Ling * through start uploading a BIOS image.
6ded66d0fSJason Ling */
7ded66d0fSJason Ling #include "firmware_handler.hpp"
8ded66d0fSJason Ling #include "flags.hpp"
9ded66d0fSJason Ling #include "image_mock.hpp"
10ded66d0fSJason Ling #include "status.hpp"
11ded66d0fSJason Ling #include "triggerable_mock.hpp"
12ded66d0fSJason Ling #include "util.hpp"
13ded66d0fSJason Ling
14ded66d0fSJason Ling #include <memory>
15ded66d0fSJason Ling #include <string>
16ded66d0fSJason Ling #include <unordered_map>
17ded66d0fSJason Ling #include <vector>
18ded66d0fSJason Ling
19ded66d0fSJason Ling #include <gtest/gtest.h>
20ded66d0fSJason Ling
21ded66d0fSJason Ling namespace ipmi_flash
22ded66d0fSJason Ling {
23ded66d0fSJason Ling namespace
24ded66d0fSJason Ling {
25ded66d0fSJason Ling
26ded66d0fSJason Ling using ::testing::Return;
27ded66d0fSJason Ling
28ded66d0fSJason Ling class IpmiOnlyTwoFirmwaresTest : public ::testing::Test
29ded66d0fSJason Ling {
30ded66d0fSJason Ling protected:
SetUp()31ded66d0fSJason Ling void SetUp() override
32ded66d0fSJason Ling {
33ded66d0fSJason Ling std::unique_ptr<ImageHandlerInterface> image =
34ded66d0fSJason Ling std::make_unique<ImageHandlerMock>();
35ded66d0fSJason Ling hashImageMock = reinterpret_cast<ImageHandlerMock*>(image.get());
36ded66d0fSJason Ling blobs.emplace_back(hashBlobId, std::move(image));
37ded66d0fSJason Ling
38ded66d0fSJason Ling image = std::make_unique<ImageHandlerMock>();
39ded66d0fSJason Ling staticImageMock = reinterpret_cast<ImageHandlerMock*>(image.get());
40ded66d0fSJason Ling blobs.emplace_back(staticLayoutBlobId, std::move(image));
41ded66d0fSJason Ling
42ded66d0fSJason Ling image = std::make_unique<ImageHandlerMock>();
43ded66d0fSJason Ling biosImageMock = reinterpret_cast<ImageHandlerMock*>(image.get());
44ded66d0fSJason Ling blobs.emplace_back(biosBlobId, std::move(image));
45ded66d0fSJason Ling
46ded66d0fSJason Ling std::unique_ptr<TriggerableActionInterface> bmcPrepareMock =
47ded66d0fSJason Ling std::make_unique<TriggerMock>();
48ded66d0fSJason Ling bmcPrepareMockPtr =
49ded66d0fSJason Ling reinterpret_cast<TriggerMock*>(bmcPrepareMock.get());
50ded66d0fSJason Ling
51ded66d0fSJason Ling std::unique_ptr<TriggerableActionInterface> bmcVerifyMock =
52ded66d0fSJason Ling std::make_unique<TriggerMock>();
53ded66d0fSJason Ling bmcVerifyMockPtr = reinterpret_cast<TriggerMock*>(bmcVerifyMock.get());
54ded66d0fSJason Ling
55ded66d0fSJason Ling std::unique_ptr<TriggerableActionInterface> bmcUpdateMock =
56ded66d0fSJason Ling std::make_unique<TriggerMock>();
57ded66d0fSJason Ling bmcUpdateMockPtr = reinterpret_cast<TriggerMock*>(bmcUpdateMock.get());
58ded66d0fSJason Ling
59ded66d0fSJason Ling std::unique_ptr<TriggerableActionInterface> biosPrepareMock =
60ded66d0fSJason Ling std::make_unique<TriggerMock>();
61ded66d0fSJason Ling biosPrepareMockPtr =
62ded66d0fSJason Ling reinterpret_cast<TriggerMock*>(biosPrepareMock.get());
63ded66d0fSJason Ling
64ded66d0fSJason Ling std::unique_ptr<TriggerableActionInterface> biosVerifyMock =
65ded66d0fSJason Ling std::make_unique<TriggerMock>();
66ded66d0fSJason Ling biosVerifyMockPtr =
67ded66d0fSJason Ling reinterpret_cast<TriggerMock*>(biosVerifyMock.get());
68ded66d0fSJason Ling
69ded66d0fSJason Ling std::unique_ptr<TriggerableActionInterface> biosUpdateMock =
70ded66d0fSJason Ling std::make_unique<TriggerMock>();
71ded66d0fSJason Ling biosUpdateMockPtr =
72ded66d0fSJason Ling reinterpret_cast<TriggerMock*>(biosUpdateMock.get());
73ded66d0fSJason Ling
74ded66d0fSJason Ling ActionMap packs;
75ded66d0fSJason Ling
76ded66d0fSJason Ling std::unique_ptr<ActionPack> bmcPack = std::make_unique<ActionPack>();
77ded66d0fSJason Ling bmcPack->preparation = std::move(bmcPrepareMock);
78ded66d0fSJason Ling bmcPack->verification = std::move(bmcVerifyMock);
79ded66d0fSJason Ling bmcPack->update = std::move(bmcUpdateMock);
80ded66d0fSJason Ling
81ded66d0fSJason Ling std::unique_ptr<ActionPack> biosPack = std::make_unique<ActionPack>();
82ded66d0fSJason Ling biosPack->preparation = std::move(biosPrepareMock);
83ded66d0fSJason Ling biosPack->verification = std::move(biosVerifyMock);
84ded66d0fSJason Ling biosPack->update = std::move(biosUpdateMock);
85ded66d0fSJason Ling
86ded66d0fSJason Ling packs[staticLayoutBlobId] = std::move(bmcPack);
87ded66d0fSJason Ling packs[biosBlobId] = std::move(biosPack);
88ded66d0fSJason Ling
89ded66d0fSJason Ling std::vector<DataHandlerPack> data;
90ded66d0fSJason Ling data.emplace_back(FirmwareFlags::UpdateFlags::ipmi, nullptr);
91ded66d0fSJason Ling
92ded66d0fSJason Ling handler = FirmwareBlobHandler::CreateFirmwareBlobHandler(
93ded66d0fSJason Ling std::move(blobs), std::move(data), std::move(packs));
94ded66d0fSJason Ling }
95ded66d0fSJason Ling
expectedState(FirmwareBlobHandler::UpdateState state)96ded66d0fSJason Ling void expectedState(FirmwareBlobHandler::UpdateState state)
97ded66d0fSJason Ling {
98ded66d0fSJason Ling auto realHandler = dynamic_cast<FirmwareBlobHandler*>(handler.get());
99ded66d0fSJason Ling EXPECT_EQ(state, realHandler->getCurrentState());
100ded66d0fSJason Ling }
101ded66d0fSJason Ling
102ded66d0fSJason Ling ImageHandlerMock *hashImageMock, *staticImageMock, *biosImageMock;
103ded66d0fSJason Ling
104ded66d0fSJason Ling std::vector<HandlerPack> blobs;
105ded66d0fSJason Ling
106ded66d0fSJason Ling std::unique_ptr<blobs::GenericBlobInterface> handler;
107ded66d0fSJason Ling
108ded66d0fSJason Ling TriggerMock *bmcPrepareMockPtr, *bmcVerifyMockPtr, *bmcUpdateMockPtr;
109ded66d0fSJason Ling TriggerMock *biosPrepareMockPtr, *biosVerifyMockPtr, *biosUpdateMockPtr;
110ded66d0fSJason Ling
111ded66d0fSJason Ling std::uint16_t session = 1;
112*b487eb47SWilly Tu std::uint16_t flags = static_cast<std::uint16_t>(blobs::OpenFlags::write) |
113*b487eb47SWilly Tu FirmwareFlags::UpdateFlags::ipmi;
114ded66d0fSJason Ling };
115ded66d0fSJason Ling
TEST_F(IpmiOnlyTwoFirmwaresTest,OpeningBiosAfterBlobFails)116ded66d0fSJason Ling TEST_F(IpmiOnlyTwoFirmwaresTest, OpeningBiosAfterBlobFails)
117ded66d0fSJason Ling {
118ded66d0fSJason Ling /* You can only have one file open at a time, and the first firmware file
119ded66d0fSJason Ling * you open locks it down
120ded66d0fSJason Ling */
12156a2273fSJason Ling EXPECT_CALL(*staticImageMock, open(staticLayoutBlobId, std::ios::out))
122ded66d0fSJason Ling .WillOnce(Return(true));
123ded66d0fSJason Ling EXPECT_CALL(*bmcPrepareMockPtr, trigger()).WillOnce(Return(true));
124ded66d0fSJason Ling
125ded66d0fSJason Ling EXPECT_TRUE(handler->open(session, flags, staticLayoutBlobId));
126ded66d0fSJason Ling expectedState(FirmwareBlobHandler::UpdateState::uploadInProgress);
127ded66d0fSJason Ling
128ded66d0fSJason Ling EXPECT_CALL(*staticImageMock, close()).WillOnce(Return());
129ded66d0fSJason Ling handler->close(session);
130ded66d0fSJason Ling
131ded66d0fSJason Ling expectedState(FirmwareBlobHandler::UpdateState::verificationPending);
132ded66d0fSJason Ling
13356a2273fSJason Ling EXPECT_CALL(*biosImageMock, open(biosBlobId, std::ios::out)).Times(0);
134ded66d0fSJason Ling EXPECT_FALSE(handler->open(session, flags, biosBlobId));
135ded66d0fSJason Ling }
136ded66d0fSJason Ling
TEST_F(IpmiOnlyTwoFirmwaresTest,OpeningHashBeforeBiosSucceeds)137ded66d0fSJason Ling TEST_F(IpmiOnlyTwoFirmwaresTest, OpeningHashBeforeBiosSucceeds)
138ded66d0fSJason Ling {
139ded66d0fSJason Ling /* Opening the hash blob does nothing special in this regard. */
14056a2273fSJason Ling EXPECT_CALL(*hashImageMock, open(hashBlobId, std::ios::out))
14156a2273fSJason Ling .WillOnce(Return(true));
142ded66d0fSJason Ling EXPECT_TRUE(handler->open(session, flags, hashBlobId));
143ded66d0fSJason Ling
144ded66d0fSJason Ling expectedState(FirmwareBlobHandler::UpdateState::uploadInProgress);
145ded66d0fSJason Ling
146ded66d0fSJason Ling EXPECT_CALL(*hashImageMock, close()).WillOnce(Return());
147ded66d0fSJason Ling handler->close(session);
148ded66d0fSJason Ling
149ded66d0fSJason Ling expectedState(FirmwareBlobHandler::UpdateState::verificationPending);
150ded66d0fSJason Ling ASSERT_FALSE(handler->canHandleBlob(verifyBlobId));
151ded66d0fSJason Ling
15256a2273fSJason Ling EXPECT_CALL(*biosImageMock, open(biosBlobId, std::ios::out))
15356a2273fSJason Ling .WillOnce(Return(true));
154ded66d0fSJason Ling EXPECT_TRUE(handler->open(session, flags, biosBlobId));
155ded66d0fSJason Ling
156ded66d0fSJason Ling expectedState(FirmwareBlobHandler::UpdateState::uploadInProgress);
157ded66d0fSJason Ling
158ded66d0fSJason Ling EXPECT_CALL(*biosImageMock, close()).WillOnce(Return());
159ded66d0fSJason Ling handler->close(session);
160ded66d0fSJason Ling }
161ded66d0fSJason Ling
162ded66d0fSJason Ling } // namespace
163ded66d0fSJason Ling } // namespace ipmi_flash
164