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