blob: 16a6498351998ba3c08fab03a6652df7269bb94b [file] [log] [blame]
Patrick Venture0cd945c2019-05-30 13:36:53 -07001/* The goal of these tests is to verify the behavior of all blob commands given
2 * the current state is updatePending. This state is achieved as an exit from
3 * verificationCompleted.
4 */
5#include "firmware_handler.hpp"
6#include "firmware_unittest.hpp"
7#include "status.hpp"
8#include "util.hpp"
9
10#include <cstdint>
11#include <string>
12#include <vector>
13
14#include <gtest/gtest.h>
15
16namespace ipmi_flash
17{
18namespace
19{
20
Patrick Ventureebe456f2019-05-30 16:40:39 -070021using ::testing::IsEmpty;
Patrick Venture0cd945c2019-05-30 13:36:53 -070022using ::testing::Return;
Patrick Venturead933832019-05-30 14:13:29 -070023using ::testing::UnorderedElementsAreArray;
Patrick Venture0cd945c2019-05-30 13:36:53 -070024
25/*
26 * There are the following calls (parameters may vary):
27 * canHandleBlob(blob)
28 * getBlobIds
29 * deleteBlob(blob)
30 * stat(blob)
31 * stat(session)
32 * open(blob)
33 * close(session)
34 * writemeta(session)
35 * write(session)
36 * read(session)
37 * commit(session)
38 *
39 * Testing canHandleBlob is uninteresting in this state. Getting the BlobIDs
40 * will inform what canHandleBlob will return.
41 */
42
43class FirmwareHandlerUpdatePendingTest : public IpmiOnlyFirmwareStaticTest
Patrick Venture9b37b092020-05-28 20:58:57 -070044{};
Patrick Venture0cd945c2019-05-30 13:36:53 -070045
46/*
47 * There are the following calls (parameters may vary):
48 * canHandleBlob(blob)
49 * getBlobIds
50 */
Patrick Venturead933832019-05-30 14:13:29 -070051TEST_F(FirmwareHandlerUpdatePendingTest, GetBlobsListHasExpectedValues)
52{
53 getToUpdatePending();
54
Patrick Venture9a69f732019-06-17 14:05:13 -070055 EXPECT_THAT(handler->getBlobIds(),
56 UnorderedElementsAreArray({updateBlobId, activeImageBlobId,
57 hashBlobId, staticLayoutBlobId}));
Patrick Venturead933832019-05-30 14:13:29 -070058}
59
Patrick Venture0cd945c2019-05-30 13:36:53 -070060/*
Patrick Venture19f5d882019-05-30 14:34:55 -070061 * open(blob) - because updatePending is in a fileOpen==false state, one can
62 * then open blobs. However, because we're in a special state, we will restrict
63 * them s.t. they can only open the updateBlobId.
64 */
65TEST_F(FirmwareHandlerUpdatePendingTest,
66 OpenUpdateBlobIdIsSuccessfulAndDoesNotChangeState)
67{
68 getToUpdatePending();
69
70 /* Opening the update blob isn't interesting, except it's required for
71 * commit() which triggers the update process.
72 */
73 EXPECT_TRUE(handler->open(session, flags, updateBlobId));
Patrick Venture6b0aa182019-05-30 14:47:32 -070074 expectedState(FirmwareBlobHandler::UpdateState::updatePending);
Patrick Venture19f5d882019-05-30 14:34:55 -070075}
76
77TEST_F(FirmwareHandlerUpdatePendingTest, OpenAnyBlobOtherThanUpdateFails)
78{
79 getToUpdatePending();
80
81 auto blobs = handler->getBlobIds();
82 for (const auto& blob : blobs)
83 {
84 if (blob == updateBlobId)
85 {
86 continue;
87 }
88 EXPECT_FALSE(handler->open(session, flags, blob));
89 }
90}
91
92/*
Patrick Venture6b0aa182019-05-30 14:47:32 -070093 * close(session) - close from this state is uninteresting.
94 */
95TEST_F(FirmwareHandlerUpdatePendingTest, CloseUpdateBlobDoesNotChangeState)
96{
97 /* Verify nothing changes when one just opens, then closes the updateBlobId.
98 */
99 getToUpdatePending();
100
101 EXPECT_TRUE(handler->open(session, flags, updateBlobId));
102
103 handler->close(session);
104
105 expectedState(FirmwareBlobHandler::UpdateState::updatePending);
106 EXPECT_TRUE(handler->canHandleBlob(updateBlobId));
107}
108
109/*
Patrick Venture94bb9702019-05-30 14:53:22 -0700110 * writemeta(session) - this will return failure.
111 */
112TEST_F(FirmwareHandlerUpdatePendingTest, WriteMetaToUpdateBlobReturnsFailure)
113{
114 getToUpdatePending();
115
116 EXPECT_TRUE(handler->open(session, flags, updateBlobId));
117 EXPECT_FALSE(handler->writeMeta(session, 0, {0x01}));
118}
119
120/*
Patrick Venture4e2fdcd2019-05-30 14:58:57 -0700121 * write(session)
122 */
123TEST_F(FirmwareHandlerUpdatePendingTest, WriteToUpdateBlobReturnsFailure)
124{
125 getToUpdatePending();
126
127 EXPECT_TRUE(handler->open(session, flags, updateBlobId));
128 EXPECT_FALSE(handler->write(session, 0, {0x01}));
129}
130
131/*
Patrick Ventureebe456f2019-05-30 16:40:39 -0700132 * read(session)
133 */
134TEST_F(FirmwareHandlerUpdatePendingTest, ReadFromUpdateBlobIdReturnsEmpty)
135{
136 getToUpdatePending();
137 EXPECT_THAT(handler->read(session, 0, 1), IsEmpty());
138}
139
140/*
Patrick Venture5f562692019-05-30 16:49:46 -0700141 * stat(blob)
Patrick Venture0cd945c2019-05-30 13:36:53 -0700142 */
Patrick Venture5f562692019-05-30 16:49:46 -0700143TEST_F(FirmwareHandlerUpdatePendingTest, StatOnActiveImageReturnsFailure)
144{
145 getToUpdatePending();
146 ASSERT_TRUE(handler->canHandleBlob(activeImageBlobId));
147
148 blobs::BlobMeta meta;
149 EXPECT_FALSE(handler->stat(activeImageBlobId, &meta));
150}
151
152TEST_F(FirmwareHandlerUpdatePendingTest, StatOnUpdateBlobReturnsFailure)
153{
154 getToUpdatePending();
155 ASSERT_TRUE(handler->canHandleBlob(updateBlobId));
156
157 blobs::BlobMeta meta;
158 EXPECT_FALSE(handler->stat(updateBlobId, &meta));
159}
160
161TEST_F(FirmwareHandlerUpdatePendingTest, StatOnNormalBlobsReturnsSuccess)
162{
163 getToUpdatePending();
164
Patrick Venture9a69f732019-06-17 14:05:13 -0700165 for (const auto& blob : startingBlobs)
Patrick Venture5f562692019-05-30 16:49:46 -0700166 {
167 ASSERT_TRUE(handler->canHandleBlob(blob));
168
169 blobs::BlobMeta meta = {};
170 EXPECT_TRUE(handler->stat(blob, &meta));
Benjamin Fair12901982019-11-12 13:55:46 -0800171 EXPECT_EQ(expectedIdleMeta, meta);
Patrick Venture5f562692019-05-30 16:49:46 -0700172 }
173}
Patrick Venture0cd945c2019-05-30 13:36:53 -0700174
175/*
Patrick Venture40d7ffc2019-05-30 17:12:06 -0700176 * stat(session)
177 * In this case, you can open updateBlobId without changing state, therefore,
178 * let's call stat() against a session against this file. This done, ahead of
179 * commit() should report the state as "other."
Patrick Venture0cd945c2019-05-30 13:36:53 -0700180 */
Patrick Venture40d7ffc2019-05-30 17:12:06 -0700181TEST_F(FirmwareHandlerUpdatePendingTest,
182 SessionStatOnUpdateBlobIdReturnsFailure)
183{
184 getToUpdatePending();
185 EXPECT_TRUE(handler->open(session, flags, updateBlobId));
186 expectedState(FirmwareBlobHandler::UpdateState::updatePending);
187
188 blobs::BlobMeta meta, expectedMeta = {};
189 expectedMeta.size = 0;
190 expectedMeta.blobState = flags;
191 expectedMeta.metadata.push_back(
Patrick Ventureda66fd82019-06-03 11:11:24 -0700192 static_cast<std::uint8_t>(ActionStatus::unknown));
Patrick Venture40d7ffc2019-05-30 17:12:06 -0700193
194 EXPECT_TRUE(handler->stat(session, &meta));
195 EXPECT_EQ(expectedMeta, meta);
196 expectedState(FirmwareBlobHandler::UpdateState::updatePending);
197}
Patrick Venture0cd945c2019-05-30 13:36:53 -0700198
199/*
Patrick Venture1a406fe2019-05-31 07:29:56 -0700200 * commit(session)
Patrick Venture0cd945c2019-05-30 13:36:53 -0700201 */
Patrick Venture1a406fe2019-05-31 07:29:56 -0700202TEST_F(FirmwareHandlerUpdatePendingTest,
203 CommitOnUpdateBlobTriggersUpdateAndChangesState)
204{
205 /* Commit triggers the update mechanism (similarly for the verifyBlobId) and
206 * changes state to updateStarted.
207 */
208 getToUpdatePending();
209 EXPECT_TRUE(handler->open(session, flags, updateBlobId));
210 expectedState(FirmwareBlobHandler::UpdateState::updatePending);
211
Patrick Venture1d66fe62019-06-03 14:57:27 -0700212 EXPECT_CALL(*updateMockPtr, trigger()).WillOnce(Return(true));
Patrick Venture1a406fe2019-05-31 07:29:56 -0700213
214 EXPECT_TRUE(handler->commit(session, {}));
215 expectedState(FirmwareBlobHandler::UpdateState::updateStarted);
216}
217
218TEST_F(FirmwareHandlerUpdatePendingTest,
219 CommitOnUpdateBlobTriggersUpdateAndReturnsFailureDoesNotChangeState)
220{
221 getToUpdatePending();
222 EXPECT_TRUE(handler->open(session, flags, updateBlobId));
223 expectedState(FirmwareBlobHandler::UpdateState::updatePending);
224
Patrick Venture1d66fe62019-06-03 14:57:27 -0700225 EXPECT_CALL(*updateMockPtr, trigger()).WillOnce(Return(false));
Patrick Venture1a406fe2019-05-31 07:29:56 -0700226
227 EXPECT_FALSE(handler->commit(session, {}));
228 expectedState(FirmwareBlobHandler::UpdateState::updatePending);
229}
Patrick Venture0cd945c2019-05-30 13:36:53 -0700230
231/*
Patrick Venturec9f62392019-06-17 12:17:26 -0700232 * deleteBlob(blob)
Patrick Venture0cd945c2019-05-30 13:36:53 -0700233 */
Patrick Venturec9f62392019-06-17 12:17:26 -0700234TEST_F(FirmwareHandlerUpdatePendingTest, DeleteUpdateAbortsProcess)
235{
236 /* It doesn't matter what blob id is used to delete in the design, so just
237 * delete the update blob id
238 */
239 getToUpdatePending();
240
241 EXPECT_CALL(*updateMockPtr, abort()).Times(0);
242
243 ASSERT_TRUE(handler->canHandleBlob(updateBlobId));
244 EXPECT_TRUE(handler->deleteBlob(updateBlobId));
245
Patrick Venturec9f62392019-06-17 12:17:26 -0700246 EXPECT_THAT(handler->getBlobIds(),
Patrick Venture9a69f732019-06-17 14:05:13 -0700247 UnorderedElementsAreArray(startingBlobs));
Patrick Venturec9f62392019-06-17 12:17:26 -0700248 expectedState(FirmwareBlobHandler::UpdateState::notYetStarted);
249}
250
251TEST_F(FirmwareHandlerUpdatePendingTest, DeleteActiveImageAbortsProcess)
252{
253 getToUpdatePending();
254
255 EXPECT_CALL(*updateMockPtr, abort()).Times(0);
256
257 ASSERT_TRUE(handler->canHandleBlob(activeImageBlobId));
258 EXPECT_TRUE(handler->deleteBlob(activeImageBlobId));
259
Patrick Venturec9f62392019-06-17 12:17:26 -0700260 EXPECT_THAT(handler->getBlobIds(),
Patrick Venture9a69f732019-06-17 14:05:13 -0700261 UnorderedElementsAreArray(startingBlobs));
Patrick Venturec9f62392019-06-17 12:17:26 -0700262 expectedState(FirmwareBlobHandler::UpdateState::notYetStarted);
263}
264
265TEST_F(FirmwareHandlerUpdatePendingTest, DeleteStaticLayoutAbortsProcess)
266{
267 getToUpdatePending();
268
269 EXPECT_CALL(*updateMockPtr, abort()).Times(0);
270
271 ASSERT_TRUE(handler->canHandleBlob(staticLayoutBlobId));
272 EXPECT_TRUE(handler->deleteBlob(staticLayoutBlobId));
273
Patrick Venturec9f62392019-06-17 12:17:26 -0700274 EXPECT_THAT(handler->getBlobIds(),
Patrick Venture9a69f732019-06-17 14:05:13 -0700275 UnorderedElementsAreArray(startingBlobs));
Patrick Venturec9f62392019-06-17 12:17:26 -0700276 expectedState(FirmwareBlobHandler::UpdateState::notYetStarted);
277}
278
279TEST_F(FirmwareHandlerUpdatePendingTest, DeleteHashAbortsProcess)
280{
281 getToUpdatePending();
282
283 EXPECT_CALL(*updateMockPtr, abort()).Times(0);
284
285 ASSERT_TRUE(handler->canHandleBlob(hashBlobId));
286 EXPECT_TRUE(handler->deleteBlob(hashBlobId));
287
Patrick Venturec9f62392019-06-17 12:17:26 -0700288 EXPECT_THAT(handler->getBlobIds(),
Patrick Venture9a69f732019-06-17 14:05:13 -0700289 UnorderedElementsAreArray(startingBlobs));
Patrick Venturec9f62392019-06-17 12:17:26 -0700290 expectedState(FirmwareBlobHandler::UpdateState::notYetStarted);
291}
Patrick Venture0cd945c2019-05-30 13:36:53 -0700292
293} // namespace
294} // namespace ipmi_flash