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