1 /* The goal of these tests is to verify the behavior of all blob commands given
2 * the current state is verificationStarted. This state is achieved as a out of
3 * verificationPending.
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
16 namespace ipmi_flash
17 {
18 namespace
19 {
20
21 using ::testing::IsEmpty;
22 using ::testing::Return;
23 using ::testing::UnorderedElementsAreArray;
24
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
43 class FirmwareHandlerVerificationStartedTest : public IpmiOnlyFirmwareStaticTest
44 {};
45
46 /*
47 * canHandleBlob(blob)
48 * getBlobIds()
49 */
TEST_F(FirmwareHandlerVerificationStartedTest,GetBlobIdsReturnsExpectedList)50 TEST_F(FirmwareHandlerVerificationStartedTest, GetBlobIdsReturnsExpectedList)
51 {
52 getToVerificationStarted(staticLayoutBlobId);
53
54 auto blobs = handler->getBlobIds();
55 EXPECT_THAT(blobs, UnorderedElementsAreArray(
56 {activeImageBlobId, staticLayoutBlobId, hashBlobId,
57 verifyBlobId}));
58
59 for (const auto& blob : blobs)
60 {
61 EXPECT_TRUE(handler->canHandleBlob(blob));
62 }
63 }
64
65 /*
66 * stat(session)
67 */
TEST_F(FirmwareHandlerVerificationStartedTest,StatOnVerifyBlobIdAfterCommitChecksStateAndReturnsRunning)68 TEST_F(FirmwareHandlerVerificationStartedTest,
69 StatOnVerifyBlobIdAfterCommitChecksStateAndReturnsRunning)
70 {
71 getToVerificationStarted(staticLayoutBlobId);
72 EXPECT_CALL(*verifyMockPtr, status())
73 .WillOnce(Return(ActionStatus::running));
74
75 blobs::BlobMeta meta, expectedMeta = {};
76 expectedMeta.size = 0;
77 expectedMeta.blobState = flags | blobs::StateFlags::committing;
78 expectedMeta.metadata.push_back(
79 static_cast<std::uint8_t>(ActionStatus::running));
80
81 EXPECT_TRUE(handler->stat(session, &meta));
82 EXPECT_EQ(expectedMeta, meta);
83 }
84
TEST_F(FirmwareHandlerVerificationStartedTest,StatOnVerifyBlobIdAfterCommitChecksStateAndReturnsOther)85 TEST_F(FirmwareHandlerVerificationStartedTest,
86 StatOnVerifyBlobIdAfterCommitChecksStateAndReturnsOther)
87 {
88 getToVerificationStarted(staticLayoutBlobId);
89 EXPECT_CALL(*verifyMockPtr, status())
90 .WillOnce(Return(ActionStatus::unknown));
91
92 blobs::BlobMeta meta, expectedMeta = {};
93 expectedMeta.size = 0;
94 expectedMeta.blobState = flags | blobs::StateFlags::committing;
95 expectedMeta.metadata.push_back(
96 static_cast<std::uint8_t>(ActionStatus::unknown));
97
98 EXPECT_TRUE(handler->stat(session, &meta));
99 EXPECT_EQ(expectedMeta, meta);
100 }
101
TEST_F(FirmwareHandlerVerificationStartedTest,StatOnVerifyBlobIdAfterCommitCheckStateAndReturnsFailed)102 TEST_F(FirmwareHandlerVerificationStartedTest,
103 StatOnVerifyBlobIdAfterCommitCheckStateAndReturnsFailed)
104 {
105 /* If the returned state from the verification handler is failed, it sets
106 * commit_error and transitions to verificationCompleted.
107 */
108 getToVerificationStarted(staticLayoutBlobId);
109 EXPECT_CALL(*verifyMockPtr, status())
110 .WillOnce(Return(ActionStatus::failed));
111
112 blobs::BlobMeta meta, expectedMeta = {};
113 expectedMeta.size = 0;
114 expectedMeta.blobState = flags | blobs::StateFlags::commit_error;
115 expectedMeta.metadata.push_back(
116 static_cast<std::uint8_t>(ActionStatus::failed));
117
118 EXPECT_TRUE(handler->stat(session, &meta));
119 EXPECT_EQ(expectedMeta, meta);
120 expectedState(FirmwareBlobHandler::UpdateState::verificationCompleted);
121 }
122
TEST_F(FirmwareHandlerVerificationStartedTest,StatOnVerifyBlobIdAfterCommitCheckStateAndReturnsSuccess)123 TEST_F(FirmwareHandlerVerificationStartedTest,
124 StatOnVerifyBlobIdAfterCommitCheckStateAndReturnsSuccess)
125 {
126 /* If the returned state from the verification handler is success, it sets
127 * committed and transitions to verificationCompleted.
128 */
129 getToVerificationStarted(staticLayoutBlobId);
130 EXPECT_CALL(*verifyMockPtr, status())
131 .WillOnce(Return(ActionStatus::success));
132
133 blobs::BlobMeta meta, expectedMeta = {};
134 expectedMeta.size = 0;
135 expectedMeta.blobState = flags | blobs::StateFlags::committed;
136 expectedMeta.metadata.push_back(
137 static_cast<std::uint8_t>(ActionStatus::success));
138
139 EXPECT_TRUE(handler->stat(session, &meta));
140 EXPECT_EQ(expectedMeta, meta);
141 expectedState(FirmwareBlobHandler::UpdateState::verificationCompleted);
142 }
143
144 /*
145 * deleteBlob(blob)
146 */
TEST_F(FirmwareHandlerVerificationStartedTest,DeleteBlobReturnsFalse)147 TEST_F(FirmwareHandlerVerificationStartedTest, DeleteBlobReturnsFalse)
148 {
149 /* Try deleting all blobs, it doesn't really matter which though because you
150 * cannot close out an open session, therefore you must fail to delete
151 * anything unless everything is closed.
152 */
153 getToVerificationStarted(staticLayoutBlobId);
154 auto blobs = handler->getBlobIds();
155 for (const auto& b : blobs)
156 {
157 EXPECT_FALSE(handler->deleteBlob(b));
158 }
159 }
160
161 /*
162 * stat(blob)
163 */
TEST_F(FirmwareHandlerVerificationStartedTest,StatOnActiveImageReturnsFailure)164 TEST_F(FirmwareHandlerVerificationStartedTest, StatOnActiveImageReturnsFailure)
165 {
166 getToVerificationStarted(staticLayoutBlobId);
167 ASSERT_TRUE(handler->canHandleBlob(activeImageBlobId));
168
169 blobs::BlobMeta meta;
170 EXPECT_FALSE(handler->stat(activeImageBlobId, &meta));
171 }
172
TEST_F(FirmwareHandlerVerificationStartedTest,StatOnActiveHashReturnsFailure)173 TEST_F(FirmwareHandlerVerificationStartedTest, StatOnActiveHashReturnsFailure)
174 {
175 getToVerificationStartedWitHashBlob();
176 ASSERT_TRUE(handler->canHandleBlob(activeHashBlobId));
177
178 blobs::BlobMeta meta;
179 EXPECT_FALSE(handler->stat(activeHashBlobId, &meta));
180 }
181
TEST_F(FirmwareHandlerVerificationStartedTest,StatOnVerifyBlobReturnsFailure)182 TEST_F(FirmwareHandlerVerificationStartedTest, StatOnVerifyBlobReturnsFailure)
183 {
184 /* the verifyBlobId is available starting at verificationPending. */
185 getToVerificationStarted(staticLayoutBlobId);
186 ASSERT_TRUE(handler->canHandleBlob(verifyBlobId));
187
188 blobs::BlobMeta meta;
189 EXPECT_FALSE(handler->stat(verifyBlobId, &meta));
190 }
191
TEST_F(FirmwareHandlerVerificationStartedTest,StatOnNormalBlobsReturnsSuccess)192 TEST_F(FirmwareHandlerVerificationStartedTest, StatOnNormalBlobsReturnsSuccess)
193 {
194 getToVerificationStarted(staticLayoutBlobId);
195
196 std::vector<std::string> testBlobs = {staticLayoutBlobId, hashBlobId};
197 for (const auto& blob : testBlobs)
198 {
199 ASSERT_TRUE(handler->canHandleBlob(blob));
200
201 blobs::BlobMeta meta = {};
202 EXPECT_TRUE(handler->stat(blob, &meta));
203 EXPECT_EQ(expectedIdleMeta, meta);
204 }
205 }
206
207 /*
208 * writemeta(session)
209 */
TEST_F(FirmwareHandlerVerificationStartedTest,WriteMetaOnVerifySessionReturnsFailure)210 TEST_F(FirmwareHandlerVerificationStartedTest,
211 WriteMetaOnVerifySessionReturnsFailure)
212 {
213 getToVerificationStarted(staticLayoutBlobId);
214
215 std::vector<std::uint8_t> bytes = {0x01, 0x02};
216 EXPECT_FALSE(handler->writeMeta(session, 0, bytes));
217 }
218
219 /*
220 * write(session)
221 */
TEST_F(FirmwareHandlerVerificationStartedTest,WriteOnVerifySessionReturnsFailure)222 TEST_F(FirmwareHandlerVerificationStartedTest,
223 WriteOnVerifySessionReturnsFailure)
224 {
225 getToVerificationStarted(staticLayoutBlobId);
226
227 std::vector<std::uint8_t> bytes = {0x01, 0x02};
228 EXPECT_FALSE(handler->write(session, 0, bytes));
229 }
230
231 /*
232 * open(blob) - there is nothing you can open, this state has an open file.
233 */
TEST_F(FirmwareHandlerVerificationStartedTest,AttemptToOpenImageFileReturnsFailure)234 TEST_F(FirmwareHandlerVerificationStartedTest,
235 AttemptToOpenImageFileReturnsFailure)
236 {
237 /* Attempt to open a file one normally can open, however, as there is
238 * already a file open, this will fail.
239 */
240 getToVerificationStarted(staticLayoutBlobId);
241
242 auto blobsToOpen = handler->getBlobIds();
243 for (const auto& blob : blobsToOpen)
244 {
245 EXPECT_FALSE(handler->open(session + 1, flags, blob));
246 }
247 }
248
249 /*
250 * read(session)
251 */
TEST_F(FirmwareHandlerVerificationStartedTest,ReadOfVerifyBlobReturnsEmpty)252 TEST_F(FirmwareHandlerVerificationStartedTest, ReadOfVerifyBlobReturnsEmpty)
253 {
254 getToVerificationStarted(staticLayoutBlobId);
255 EXPECT_THAT(handler->read(session, 0, 1), IsEmpty());
256 }
257
258 /*
259 * commit(session)
260 */
TEST_F(FirmwareHandlerVerificationStartedTest,CommitOnVerifyDuringVerificationHasNoImpact)261 TEST_F(FirmwareHandlerVerificationStartedTest,
262 CommitOnVerifyDuringVerificationHasNoImpact)
263 {
264 getToVerificationStarted(staticLayoutBlobId);
265 EXPECT_TRUE(handler->commit(session, {}));
266 expectedState(FirmwareBlobHandler::UpdateState::verificationStarted);
267 }
268
269 /*
270 * close(session) - close while state if verificationStarted without calling
271 * stat first will abort.
272 */
TEST_F(FirmwareHandlerVerificationStartedTest,CloseOnVerifyDuringVerificationAbortsProcess)273 TEST_F(FirmwareHandlerVerificationStartedTest,
274 CloseOnVerifyDuringVerificationAbortsProcess)
275 {
276 getToVerificationStarted(staticLayoutBlobId);
277 EXPECT_CALL(*verifyMockPtr, abort()).Times(1);
278
279 EXPECT_TRUE(handler->close(session));
280
281 EXPECT_THAT(handler->getBlobIds(),
282 UnorderedElementsAreArray(startingBlobs));
283
284 expectedState(FirmwareBlobHandler::UpdateState::notYetStarted);
285 }
286
287 /*
288 * expire(session)
289 */
TEST_F(FirmwareHandlerVerificationStartedTest,ExpireOnSessionDuringVerificationAbortsProcess)290 TEST_F(FirmwareHandlerVerificationStartedTest,
291 ExpireOnSessionDuringVerificationAbortsProcess)
292 {
293 getToVerificationStarted(staticLayoutBlobId);
294 EXPECT_CALL(*verifyMockPtr, abort()).Times(0);
295
296 EXPECT_TRUE(handler->expire(session));
297
298 EXPECT_THAT(handler->getBlobIds(),
299 UnorderedElementsAreArray(startingBlobs));
300
301 expectedState(FirmwareBlobHandler::UpdateState::notYetStarted);
302 }
303
304 } // namespace
305 } // namespace ipmi_flash
306