1*ded66d0fSJason Ling /* The goal of these tests is to verify the behavior of all blob commands given
2*ded66d0fSJason Ling * the current state is updateStarted. This state is achieved as an exit from
3*ded66d0fSJason Ling * updatePending.
4*ded66d0fSJason Ling */
5*ded66d0fSJason Ling #include "firmware_handler.hpp"
6*ded66d0fSJason Ling #include "firmware_unittest.hpp"
7*ded66d0fSJason Ling #include "status.hpp"
8*ded66d0fSJason Ling #include "util.hpp"
9*ded66d0fSJason Ling
10*ded66d0fSJason Ling #include <cstdint>
11*ded66d0fSJason Ling #include <string>
12*ded66d0fSJason Ling #include <vector>
13*ded66d0fSJason Ling
14*ded66d0fSJason Ling #include <gtest/gtest.h>
15*ded66d0fSJason Ling
16*ded66d0fSJason Ling namespace ipmi_flash
17*ded66d0fSJason Ling {
18*ded66d0fSJason Ling namespace
19*ded66d0fSJason Ling {
20*ded66d0fSJason Ling
21*ded66d0fSJason Ling using ::testing::IsEmpty;
22*ded66d0fSJason Ling using ::testing::Return;
23*ded66d0fSJason Ling using ::testing::UnorderedElementsAreArray;
24*ded66d0fSJason Ling
25*ded66d0fSJason Ling /*
26*ded66d0fSJason Ling * There are the following calls (parameters may vary):
27*ded66d0fSJason Ling * canHandleBlob(blob)
28*ded66d0fSJason Ling * getBlobIds
29*ded66d0fSJason Ling * deleteBlob(blob)
30*ded66d0fSJason Ling * stat(blob)
31*ded66d0fSJason Ling * stat(session)
32*ded66d0fSJason Ling * open(blob)
33*ded66d0fSJason Ling * close(session)
34*ded66d0fSJason Ling * writemeta(session)
35*ded66d0fSJason Ling * write(session)
36*ded66d0fSJason Ling * read(session)
37*ded66d0fSJason Ling * commit(session)
38*ded66d0fSJason Ling */
39*ded66d0fSJason Ling
40*ded66d0fSJason Ling class FirmwareHandlerUpdateStartedTest : public IpmiOnlyFirmwareStaticTest
41*ded66d0fSJason Ling {};
42*ded66d0fSJason Ling
43*ded66d0fSJason Ling /*
44*ded66d0fSJason Ling * open(blob)
45*ded66d0fSJason Ling */
TEST_F(FirmwareHandlerUpdateStartedTest,AttemptToOpenFilesReturnsFailure)46*ded66d0fSJason Ling TEST_F(FirmwareHandlerUpdateStartedTest, AttemptToOpenFilesReturnsFailure)
47*ded66d0fSJason Ling {
48*ded66d0fSJason Ling /* In state updateStarted a file is open, which means no others can be. */
49*ded66d0fSJason Ling getToUpdateStarted();
50*ded66d0fSJason Ling
51*ded66d0fSJason Ling auto blobsToOpen = handler->getBlobIds();
52*ded66d0fSJason Ling for (const auto& blob : blobsToOpen)
53*ded66d0fSJason Ling {
54*ded66d0fSJason Ling EXPECT_FALSE(handler->open(session + 1, flags, blob));
55*ded66d0fSJason Ling }
56*ded66d0fSJason Ling }
57*ded66d0fSJason Ling
58*ded66d0fSJason Ling /* canHandleBlob(blob)
59*ded66d0fSJason Ling * getBlobIds
60*ded66d0fSJason Ling */
TEST_F(FirmwareHandlerUpdateStartedTest,VerifyListOfBlobs)61*ded66d0fSJason Ling TEST_F(FirmwareHandlerUpdateStartedTest, VerifyListOfBlobs)
62*ded66d0fSJason Ling {
63*ded66d0fSJason Ling getToUpdateStarted();
64*ded66d0fSJason Ling
65*ded66d0fSJason Ling EXPECT_THAT(
66*ded66d0fSJason Ling handler->getBlobIds(),
67*ded66d0fSJason Ling UnorderedElementsAreArray(
68*ded66d0fSJason Ling {updateBlobId, hashBlobId, activeImageBlobId, staticLayoutBlobId}));
69*ded66d0fSJason Ling }
70*ded66d0fSJason Ling
71*ded66d0fSJason Ling /*
72*ded66d0fSJason Ling * deleteBlob(blob)
73*ded66d0fSJason Ling */
TEST_F(FirmwareHandlerUpdateStartedTest,DeleteBlobReturnsFalse)74*ded66d0fSJason Ling TEST_F(FirmwareHandlerUpdateStartedTest, DeleteBlobReturnsFalse)
75*ded66d0fSJason Ling {
76*ded66d0fSJason Ling /* Try deleting all blobs, it doesn't really matter which though because you
77*ded66d0fSJason Ling * cannot close out an open session, therefore you must fail to delete
78*ded66d0fSJason Ling * anything unless everything is closed.
79*ded66d0fSJason Ling */
80*ded66d0fSJason Ling getToUpdateStarted();
81*ded66d0fSJason Ling auto blobs = handler->getBlobIds();
82*ded66d0fSJason Ling for (const auto& b : blobs)
83*ded66d0fSJason Ling {
84*ded66d0fSJason Ling EXPECT_FALSE(handler->deleteBlob(b));
85*ded66d0fSJason Ling }
86*ded66d0fSJason Ling }
87*ded66d0fSJason Ling
88*ded66d0fSJason Ling /*
89*ded66d0fSJason Ling * stat(blob)
90*ded66d0fSJason Ling */
TEST_F(FirmwareHandlerUpdateStartedTest,StatOnActiveImageReturnsFailure)91*ded66d0fSJason Ling TEST_F(FirmwareHandlerUpdateStartedTest, StatOnActiveImageReturnsFailure)
92*ded66d0fSJason Ling {
93*ded66d0fSJason Ling getToUpdateStarted();
94*ded66d0fSJason Ling
95*ded66d0fSJason Ling ASSERT_TRUE(handler->canHandleBlob(activeImageBlobId));
96*ded66d0fSJason Ling
97*ded66d0fSJason Ling blobs::BlobMeta meta;
98*ded66d0fSJason Ling EXPECT_FALSE(handler->stat(activeImageBlobId, &meta));
99*ded66d0fSJason Ling }
100*ded66d0fSJason Ling
TEST_F(FirmwareHandlerUpdateStartedTest,StatOnUpdateBlobReturnsFailure)101*ded66d0fSJason Ling TEST_F(FirmwareHandlerUpdateStartedTest, StatOnUpdateBlobReturnsFailure)
102*ded66d0fSJason Ling {
103*ded66d0fSJason Ling getToUpdateStarted();
104*ded66d0fSJason Ling
105*ded66d0fSJason Ling ASSERT_TRUE(handler->canHandleBlob(updateBlobId));
106*ded66d0fSJason Ling
107*ded66d0fSJason Ling blobs::BlobMeta meta;
108*ded66d0fSJason Ling EXPECT_FALSE(handler->stat(updateBlobId, &meta));
109*ded66d0fSJason Ling }
110*ded66d0fSJason Ling
TEST_F(FirmwareHandlerUpdateStartedTest,StatOnNormalBlobsReturnsSuccess)111*ded66d0fSJason Ling TEST_F(FirmwareHandlerUpdateStartedTest, StatOnNormalBlobsReturnsSuccess)
112*ded66d0fSJason Ling {
113*ded66d0fSJason Ling getToUpdateStarted();
114*ded66d0fSJason Ling
115*ded66d0fSJason Ling std::vector<std::string> testBlobs = {staticLayoutBlobId, hashBlobId};
116*ded66d0fSJason Ling for (const auto& blob : testBlobs)
117*ded66d0fSJason Ling {
118*ded66d0fSJason Ling ASSERT_TRUE(handler->canHandleBlob(blob));
119*ded66d0fSJason Ling
120*ded66d0fSJason Ling blobs::BlobMeta meta = {};
121*ded66d0fSJason Ling EXPECT_TRUE(handler->stat(blob, &meta));
122*ded66d0fSJason Ling EXPECT_EQ(expectedIdleMeta, meta);
123*ded66d0fSJason Ling }
124*ded66d0fSJason Ling }
125*ded66d0fSJason Ling
126*ded66d0fSJason Ling /*
127*ded66d0fSJason Ling * writemeta(session)
128*ded66d0fSJason Ling */
TEST_F(FirmwareHandlerUpdateStartedTest,WriteMetaToUpdateBlobReturnsFailure)129*ded66d0fSJason Ling TEST_F(FirmwareHandlerUpdateStartedTest, WriteMetaToUpdateBlobReturnsFailure)
130*ded66d0fSJason Ling {
131*ded66d0fSJason Ling getToUpdateStarted();
132*ded66d0fSJason Ling EXPECT_FALSE(handler->writeMeta(session, 0, {0x01}));
133*ded66d0fSJason Ling }
134*ded66d0fSJason Ling
135*ded66d0fSJason Ling /*
136*ded66d0fSJason Ling * write(session)
137*ded66d0fSJason Ling */
TEST_F(FirmwareHandlerUpdateStartedTest,WriteToUpdateBlobReturnsFailure)138*ded66d0fSJason Ling TEST_F(FirmwareHandlerUpdateStartedTest, WriteToUpdateBlobReturnsFailure)
139*ded66d0fSJason Ling {
140*ded66d0fSJason Ling getToUpdateStarted();
141*ded66d0fSJason Ling EXPECT_FALSE(handler->write(session, 0, {0x01}));
142*ded66d0fSJason Ling }
143*ded66d0fSJason Ling
144*ded66d0fSJason Ling /*
145*ded66d0fSJason Ling * read(session)
146*ded66d0fSJason Ling */
TEST_F(FirmwareHandlerUpdateStartedTest,ReadFromUpdateBlobReturnsEmpty)147*ded66d0fSJason Ling TEST_F(FirmwareHandlerUpdateStartedTest, ReadFromUpdateBlobReturnsEmpty)
148*ded66d0fSJason Ling {
149*ded66d0fSJason Ling getToUpdateStarted();
150*ded66d0fSJason Ling EXPECT_THAT(handler->read(session, 0, 1), IsEmpty());
151*ded66d0fSJason Ling }
152*ded66d0fSJason Ling
153*ded66d0fSJason Ling /*
154*ded66d0fSJason Ling * commit(session)
155*ded66d0fSJason Ling */
TEST_F(FirmwareHandlerUpdateStartedTest,CallingCommitShouldReturnTrueAndHaveNoEffect)156*ded66d0fSJason Ling TEST_F(FirmwareHandlerUpdateStartedTest,
157*ded66d0fSJason Ling CallingCommitShouldReturnTrueAndHaveNoEffect)
158*ded66d0fSJason Ling {
159*ded66d0fSJason Ling getToUpdateStarted();
160*ded66d0fSJason Ling EXPECT_CALL(*updateMockPtr, trigger()).Times(0);
161*ded66d0fSJason Ling
162*ded66d0fSJason Ling EXPECT_TRUE(handler->commit(session, {}));
163*ded66d0fSJason Ling expectedState(FirmwareBlobHandler::UpdateState::updateStarted);
164*ded66d0fSJason Ling }
165*ded66d0fSJason Ling
166*ded66d0fSJason Ling /*
167*ded66d0fSJason Ling * stat(session) - this will trigger a check, and the state may change.
168*ded66d0fSJason Ling */
TEST_F(FirmwareHandlerUpdateStartedTest,CallStatChecksActionStatusReturnsRunningDoesNotChangeState)169*ded66d0fSJason Ling TEST_F(FirmwareHandlerUpdateStartedTest,
170*ded66d0fSJason Ling CallStatChecksActionStatusReturnsRunningDoesNotChangeState)
171*ded66d0fSJason Ling {
172*ded66d0fSJason Ling getToUpdateStarted();
173*ded66d0fSJason Ling EXPECT_CALL(*updateMockPtr, status())
174*ded66d0fSJason Ling .WillOnce(Return(ActionStatus::running));
175*ded66d0fSJason Ling
176*ded66d0fSJason Ling blobs::BlobMeta meta, expectedMeta = {};
177*ded66d0fSJason Ling expectedMeta.size = 0;
178*ded66d0fSJason Ling expectedMeta.blobState = flags | blobs::StateFlags::committing;
179*ded66d0fSJason Ling expectedMeta.metadata.push_back(
180*ded66d0fSJason Ling static_cast<std::uint8_t>(ActionStatus::running));
181*ded66d0fSJason Ling
182*ded66d0fSJason Ling EXPECT_TRUE(handler->stat(session, &meta));
183*ded66d0fSJason Ling EXPECT_EQ(expectedMeta, meta);
184*ded66d0fSJason Ling expectedState(FirmwareBlobHandler::UpdateState::updateStarted);
185*ded66d0fSJason Ling }
186*ded66d0fSJason Ling
TEST_F(FirmwareHandlerUpdateStartedTest,CallStatChecksActionStatusReturnsFailedChangesStateToCompleted)187*ded66d0fSJason Ling TEST_F(FirmwareHandlerUpdateStartedTest,
188*ded66d0fSJason Ling CallStatChecksActionStatusReturnsFailedChangesStateToCompleted)
189*ded66d0fSJason Ling {
190*ded66d0fSJason Ling getToUpdateStarted();
191*ded66d0fSJason Ling EXPECT_CALL(*updateMockPtr, status())
192*ded66d0fSJason Ling .WillOnce(Return(ActionStatus::failed));
193*ded66d0fSJason Ling
194*ded66d0fSJason Ling blobs::BlobMeta meta, expectedMeta = {};
195*ded66d0fSJason Ling expectedMeta.size = 0;
196*ded66d0fSJason Ling expectedMeta.blobState = flags | blobs::StateFlags::commit_error;
197*ded66d0fSJason Ling expectedMeta.metadata.push_back(
198*ded66d0fSJason Ling static_cast<std::uint8_t>(ActionStatus::failed));
199*ded66d0fSJason Ling
200*ded66d0fSJason Ling EXPECT_TRUE(handler->stat(session, &meta));
201*ded66d0fSJason Ling EXPECT_EQ(expectedMeta, meta);
202*ded66d0fSJason Ling expectedState(FirmwareBlobHandler::UpdateState::updateCompleted);
203*ded66d0fSJason Ling }
204*ded66d0fSJason Ling
TEST_F(FirmwareHandlerUpdateStartedTest,CallStatChecksActionStatusReturnsSuccessChangesStateToCompleted)205*ded66d0fSJason Ling TEST_F(FirmwareHandlerUpdateStartedTest,
206*ded66d0fSJason Ling CallStatChecksActionStatusReturnsSuccessChangesStateToCompleted)
207*ded66d0fSJason Ling {
208*ded66d0fSJason Ling getToUpdateStarted();
209*ded66d0fSJason Ling EXPECT_CALL(*updateMockPtr, status())
210*ded66d0fSJason Ling .WillOnce(Return(ActionStatus::success));
211*ded66d0fSJason Ling
212*ded66d0fSJason Ling blobs::BlobMeta meta, expectedMeta = {};
213*ded66d0fSJason Ling expectedMeta.size = 0;
214*ded66d0fSJason Ling expectedMeta.blobState = flags | blobs::StateFlags::committed;
215*ded66d0fSJason Ling expectedMeta.metadata.push_back(
216*ded66d0fSJason Ling static_cast<std::uint8_t>(ActionStatus::success));
217*ded66d0fSJason Ling
218*ded66d0fSJason Ling EXPECT_TRUE(handler->stat(session, &meta));
219*ded66d0fSJason Ling EXPECT_EQ(expectedMeta, meta);
220*ded66d0fSJason Ling expectedState(FirmwareBlobHandler::UpdateState::updateCompleted);
221*ded66d0fSJason Ling }
222*ded66d0fSJason Ling
223*ded66d0fSJason Ling /*
224*ded66d0fSJason Ling * close(session) - this will abort.
225*ded66d0fSJason Ling */
TEST_F(FirmwareHandlerUpdateStartedTest,CloseOnUpdateDuringUpdateAbortsProcess)226*ded66d0fSJason Ling TEST_F(FirmwareHandlerUpdateStartedTest, CloseOnUpdateDuringUpdateAbortsProcess)
227*ded66d0fSJason Ling {
228*ded66d0fSJason Ling getToUpdateStarted();
229*ded66d0fSJason Ling EXPECT_CALL(*updateMockPtr, abort()).Times(1);
230*ded66d0fSJason Ling
231*ded66d0fSJason Ling EXPECT_TRUE(handler->close(session));
232*ded66d0fSJason Ling
233*ded66d0fSJason Ling EXPECT_THAT(handler->getBlobIds(),
234*ded66d0fSJason Ling UnorderedElementsAreArray(startingBlobs));
235*ded66d0fSJason Ling
236*ded66d0fSJason Ling expectedState(FirmwareBlobHandler::UpdateState::notYetStarted);
237*ded66d0fSJason Ling }
238*ded66d0fSJason Ling
239*ded66d0fSJason Ling /*
240*ded66d0fSJason Ling * expire(session)
241*ded66d0fSJason Ling */
TEST_F(FirmwareHandlerUpdateStartedTest,ExpireOnUpdateDuringUpdateAbortsProcess)242*ded66d0fSJason Ling TEST_F(FirmwareHandlerUpdateStartedTest,
243*ded66d0fSJason Ling ExpireOnUpdateDuringUpdateAbortsProcess)
244*ded66d0fSJason Ling {
245*ded66d0fSJason Ling getToUpdateStarted();
246*ded66d0fSJason Ling EXPECT_CALL(*updateMockPtr, abort()).Times(0);
247*ded66d0fSJason Ling
248*ded66d0fSJason Ling ASSERT_TRUE(handler->expire(session));
249*ded66d0fSJason Ling
250*ded66d0fSJason Ling EXPECT_THAT(handler->getBlobIds(),
251*ded66d0fSJason Ling UnorderedElementsAreArray(startingBlobs));
252*ded66d0fSJason Ling
253*ded66d0fSJason Ling expectedState(FirmwareBlobHandler::UpdateState::notYetStarted);
254*ded66d0fSJason Ling }
255*ded66d0fSJason Ling
256*ded66d0fSJason Ling } // namespace
257*ded66d0fSJason Ling } // namespace ipmi_flash
258