blob: 11133898ade3b746052ccd07bcade7d97d7c6d9e [file] [log] [blame]
Patrick Venture61d2ed42019-05-23 18:16:31 -07001/**
2 * The goal of these tests is to verify the behavior of all blob commands given
3 * the current state is verificationPending. This state is achieved as a
4 * transition out of uploadInProgress.
5 */
6#include "firmware_handler.hpp"
7#include "firmware_unittest.hpp"
Patrick Venture01a33272019-05-23 19:48:22 -07008#include "status.hpp"
Patrick Venture61d2ed42019-05-23 18:16:31 -07009#include "util.hpp"
10
11#include <cstdint>
12#include <string>
13#include <vector>
14
15#include <gtest/gtest.h>
16
17namespace ipmi_flash
18{
19namespace
20{
21
22using ::testing::Return;
23
24/*
25 * There are the following calls (parameters may vary):
26 * canHandleBlob(blob)
27 * getBlobIds
28 * deleteBlob(blob)
29 * stat(blob)
30 * stat(session)
31 * open(blob)
32 * close(session)
33 * writemeta(session)
34 * write(session)
35 * read(session)
36 * commit(session)
37 *
38 * Testing canHandleBlob is uninteresting in this state. Getting the BlobIDs
39 * will inform what canHandleBlob will return.
40 */
41
42class FirmwareHandlerVerificationPendingTest : public IpmiOnlyFirmwareStaticTest
43{
44 protected:
45 void getToVerificationPending(const std::string& blobId)
46 {
47 auto realHandler = dynamic_cast<FirmwareBlobHandler*>(handler.get());
48 EXPECT_CALL(imageMock, open(blobId)).WillOnce(Return(true));
49 EXPECT_TRUE(handler->open(session, flags, blobId));
50 EXPECT_EQ(FirmwareBlobHandler::UpdateState::uploadInProgress,
51 realHandler->getCurrentState());
52 EXPECT_CALL(imageMock, close()).WillRepeatedly(Return());
53 handler->close(session);
54 EXPECT_EQ(FirmwareBlobHandler::UpdateState::verificationPending,
55 realHandler->getCurrentState());
56 }
57
58 std::uint16_t session = 1;
59 std::uint16_t flags =
60 blobs::OpenFlags::write | FirmwareBlobHandler::UpdateFlags::ipmi;
61};
62
63/*
64 * getBlobIds
Patrick Venture61d2ed42019-05-23 18:16:31 -070065 */
Patrick Venture61d2ed42019-05-23 18:16:31 -070066TEST_F(FirmwareHandlerVerificationPendingTest, VerifyBlobIdAvailableInState)
67{
68 /* Only in the verificationPending state (and later), should the
69 * verifyBlobId be present. */
70
71 /* TODO: Add this test in when the change is made. */
72 // EXPECT_FALSE(handler->canHandleBlob(verifyBlobId));
73 getToVerificationPending(staticLayoutBlobId);
74 EXPECT_TRUE(handler->canHandleBlob(verifyBlobId));
Patrick Ventureb386b862019-05-23 18:42:54 -070075 EXPECT_TRUE(handler->canHandleBlob(activeImageBlobId));
Patrick Venture61d2ed42019-05-23 18:16:31 -070076}
77
Patrick Ventureb386b862019-05-23 18:42:54 -070078/*
79 * delete(blob) TODO: Implement this.
80 */
81
82/*
83 * stat(blob)
84 */
85TEST_F(FirmwareHandlerVerificationPendingTest, StatOnActiveImageReturnsFailure)
86{
87 getToVerificationPending(staticLayoutBlobId);
88
89 blobs::BlobMeta meta;
90 EXPECT_FALSE(handler->stat(activeImageBlobId, &meta));
91}
92
93TEST_F(FirmwareHandlerVerificationPendingTest, StatOnActiveHashReturnsFailure)
94{
95 getToVerificationPending(hashBlobId);
96
97 blobs::BlobMeta meta;
98 EXPECT_FALSE(handler->stat(activeHashBlobId, &meta));
99}
100
101TEST_F(FirmwareHandlerVerificationPendingTest,
102 StatOnVerificationBlobReturnsFailure)
103{
104 getToVerificationPending(hashBlobId);
105
106 blobs::BlobMeta meta;
107 EXPECT_FALSE(handler->stat(verifyBlobId, &meta));
108}
109
110TEST_F(FirmwareHandlerVerificationPendingTest, StatOnNormalBlobsReturnsSuccess)
111{
112 getToVerificationPending(staticLayoutBlobId);
113
114 blobs::BlobMeta expected;
115 expected.blobState = FirmwareBlobHandler::UpdateFlags::ipmi;
116 expected.size = 0;
117
118 std::vector<std::string> testBlobs = {staticLayoutBlobId, hashBlobId};
119 for (const auto& blob : testBlobs)
120 {
121 blobs::BlobMeta meta = {};
122 EXPECT_TRUE(handler->stat(blob, &meta));
123 EXPECT_EQ(expected, meta);
124 }
125}
126
127/*
Patrick Ventureb386b862019-05-23 18:42:54 -0700128 * open(blob)
129 */
Patrick Ventureda8fcd12019-05-23 18:53:50 -0700130TEST_F(FirmwareHandlerVerificationPendingTest, OpenVerifyBlobSucceeds)
131{
132 getToVerificationPending(staticLayoutBlobId);
133
134 /* the session is safe because it was already closed to get to this state.
135 */
136 EXPECT_TRUE(handler->open(session, flags, verifyBlobId));
137}
138
139TEST_F(FirmwareHandlerVerificationPendingTest, OpenActiveImageBlobFails)
140{
141 /* Try opening the active blob Id. This test is equivalent to trying to
142 * open the active hash blob id, in that neither are ever allowed.
143 */
144 getToVerificationPending(staticLayoutBlobId);
145 EXPECT_FALSE(handler->open(session, flags, activeImageBlobId));
146}
147
148TEST_F(FirmwareHandlerVerificationPendingTest,
149 OpenImageBlobTransitionsToUploadInProgress)
150{
151 getToVerificationPending(staticLayoutBlobId);
152 EXPECT_CALL(imageMock, open(staticLayoutBlobId)).WillOnce(Return(true));
153 EXPECT_TRUE(handler->open(session, flags, staticLayoutBlobId));
154
155 auto realHandler = dynamic_cast<FirmwareBlobHandler*>(handler.get());
156 EXPECT_EQ(FirmwareBlobHandler::UpdateState::uploadInProgress,
157 realHandler->getCurrentState());
158}
159
160/*
Patrick Venture1e389c92019-05-23 19:15:05 -0700161 * close(session)
162 */
163TEST_F(FirmwareHandlerVerificationPendingTest,
164 ClosingVerifyBlobDoesNotChangeState)
165{
166 getToVerificationPending(staticLayoutBlobId);
167 EXPECT_TRUE(handler->open(session, flags, verifyBlobId));
168
169 auto realHandler = dynamic_cast<FirmwareBlobHandler*>(handler.get());
170 EXPECT_EQ(FirmwareBlobHandler::UpdateState::verificationPending,
171 realHandler->getCurrentState());
172
173 handler->close(session);
174
175 EXPECT_EQ(FirmwareBlobHandler::UpdateState::verificationPending,
176 realHandler->getCurrentState());
177}
178
179/*
Patrick Venture19044e12019-05-23 19:30:28 -0700180 * commit(session)
181 */
182TEST_F(FirmwareHandlerVerificationPendingTest,
183 CommitOnVerifyBlobTriggersVerificationAndStateTransition)
184{
185 getToVerificationPending(staticLayoutBlobId);
186 EXPECT_TRUE(handler->open(session, flags, verifyBlobId));
187 EXPECT_CALL(*verifyMockPtr, triggerVerification()).WillOnce(Return(true));
188
189 EXPECT_TRUE(handler->commit(session, {}));
190
191 auto realHandler = dynamic_cast<FirmwareBlobHandler*>(handler.get());
192 EXPECT_EQ(FirmwareBlobHandler::UpdateState::verificationStarted,
193 realHandler->getCurrentState());
194}
195
196/*
Patrick Ventureda8fcd12019-05-23 18:53:50 -0700197 * stat(session) - in this state, you can only open(verifyBlobId) without
198 * changing state.
199 */
Patrick Venture01a33272019-05-23 19:48:22 -0700200TEST_F(FirmwareHandlerVerificationPendingTest, StatOnVerifyBlobIdReturnsState)
201{
202 /* If this is called before commit(), it's still verificationPending, so it
203 * just returns the state is other
204 */
205 getToVerificationPending(staticLayoutBlobId);
206 EXPECT_TRUE(handler->open(session, flags, verifyBlobId));
207 EXPECT_CALL(*verifyMockPtr, triggerVerification()).Times(0);
208 EXPECT_CALL(*verifyMockPtr, checkVerificationState()).Times(0);
209
210 blobs::BlobMeta meta, expectedMeta = {};
211 expectedMeta.size = 0;
212 expectedMeta.blobState = flags;
213 expectedMeta.metadata.push_back(
214 static_cast<std::uint8_t>(VerifyCheckResponses::other));
215
216 EXPECT_TRUE(handler->stat(session, &meta));
217 EXPECT_EQ(expectedMeta, meta);
218}
219
220TEST_F(FirmwareHandlerVerificationPendingTest,
221 StatOnVerifyBlobIdAfterCommitChecksStateAndReturnsRunning)
222{
223 getToVerificationPending(staticLayoutBlobId);
224 EXPECT_TRUE(handler->open(session, flags, verifyBlobId));
225 EXPECT_CALL(*verifyMockPtr, triggerVerification()).WillOnce(Return(true));
226 EXPECT_CALL(*verifyMockPtr, checkVerificationState())
227 .WillOnce(Return(VerifyCheckResponses::running));
228
229 blobs::BlobMeta meta, expectedMeta = {};
230 expectedMeta.size = 0;
231 expectedMeta.blobState = flags | blobs::StateFlags::committing;
232 expectedMeta.metadata.push_back(
233 static_cast<std::uint8_t>(VerifyCheckResponses::running));
234
235 EXPECT_TRUE(handler->commit(session, {}));
236 EXPECT_TRUE(handler->stat(session, &meta));
237 EXPECT_EQ(expectedMeta, meta);
238}
239
240TEST_F(FirmwareHandlerVerificationPendingTest,
241 StatOnVerifyBlobIdAfterCommitCheckStateAndReturnsFailed)
242{
243 /* If the returned state from the verification handler is failed, it sets
244 * commit_error and transitions to verificationCompleted.
245 */
246 getToVerificationPending(staticLayoutBlobId);
247 EXPECT_TRUE(handler->open(session, flags, verifyBlobId));
248 EXPECT_CALL(*verifyMockPtr, triggerVerification()).WillOnce(Return(true));
249 EXPECT_CALL(*verifyMockPtr, checkVerificationState())
250 .WillOnce(Return(VerifyCheckResponses::failed));
251
252 blobs::BlobMeta meta, expectedMeta = {};
253 expectedMeta.size = 0;
254 expectedMeta.blobState = flags | blobs::StateFlags::commit_error;
255 expectedMeta.metadata.push_back(
256 static_cast<std::uint8_t>(VerifyCheckResponses::failed));
257
258 auto realHandler = dynamic_cast<FirmwareBlobHandler*>(handler.get());
259 EXPECT_EQ(FirmwareBlobHandler::UpdateState::verificationPending,
260 realHandler->getCurrentState());
261
262 EXPECT_TRUE(handler->commit(session, {}));
263
264 EXPECT_EQ(FirmwareBlobHandler::UpdateState::verificationStarted,
265 realHandler->getCurrentState());
266
267 EXPECT_TRUE(handler->stat(session, &meta));
268 EXPECT_EQ(expectedMeta, meta);
269
270 EXPECT_EQ(FirmwareBlobHandler::UpdateState::verificationCompleted,
271 realHandler->getCurrentState());
272}
273
274TEST_F(FirmwareHandlerVerificationPendingTest,
275 StatOnVerifyBlobIdAfterCommitCheckStateAndReturnsSuccess)
276{
277 /* If the returned state from the verification handler is success, it sets
278 * committed and transitions to verificationCompleted.
279 */
280 getToVerificationPending(staticLayoutBlobId);
281 EXPECT_TRUE(handler->open(session, flags, verifyBlobId));
282 EXPECT_CALL(*verifyMockPtr, triggerVerification()).WillOnce(Return(true));
283 EXPECT_CALL(*verifyMockPtr, checkVerificationState())
284 .WillOnce(Return(VerifyCheckResponses::success));
285
286 blobs::BlobMeta meta, expectedMeta = {};
287 expectedMeta.size = 0;
288 expectedMeta.blobState = flags | blobs::StateFlags::committed;
289 expectedMeta.metadata.push_back(
290 static_cast<std::uint8_t>(VerifyCheckResponses::success));
291
292 auto realHandler = dynamic_cast<FirmwareBlobHandler*>(handler.get());
293 EXPECT_EQ(FirmwareBlobHandler::UpdateState::verificationPending,
294 realHandler->getCurrentState());
295
296 EXPECT_TRUE(handler->commit(session, {}));
297
298 EXPECT_EQ(FirmwareBlobHandler::UpdateState::verificationStarted,
299 realHandler->getCurrentState());
300
301 EXPECT_TRUE(handler->stat(session, &meta));
302 EXPECT_EQ(expectedMeta, meta);
303
304 EXPECT_EQ(FirmwareBlobHandler::UpdateState::verificationCompleted,
305 realHandler->getCurrentState());
306}
307
308/* TODO: Once verificationCompleted is the state, canHandleBlob should accept
309 * updateBlobId.
310 */
Patrick Ventureda8fcd12019-05-23 18:53:50 -0700311
Patrick Ventureb386b862019-05-23 18:42:54 -0700312/*
Patrick Ventureb386b862019-05-23 18:42:54 -0700313 * writemeta(session)
314 */
315/*
316 * write(session)
317 */
318/*
319 * read(session)
320 */
Patrick Ventureb386b862019-05-23 18:42:54 -0700321
Patrick Venture61d2ed42019-05-23 18:16:31 -0700322} // namespace
323} // namespace ipmi_flash