blob: 49214c1705fc914a8450a7915d37b22a83b20d82 [file] [log] [blame]
Patrick Ventureebcc5222019-05-23 10:36:40 -07001/**
2 * The goal of these tests is to verify the behavior of all blob commands given
3 * the current state is uploadInProgress. This state is achieved when an image
4 * or hash blob is opened and the handler is expected to receive bytes.
5 */
6#include "firmware_handler.hpp"
7#include "firmware_unittest.hpp"
8
9#include <gtest/gtest.h>
10
11namespace ipmi_flash
12{
13namespace
14{
15
16using ::testing::Return;
17using ::testing::UnorderedElementsAreArray;
18
19/*
20 * There are the following calls (parameters may vary):
21 * canHandleBlob(blob)
22 * getBlobIds
23 * deleteBlob(blob)
24 * stat(blob)
25 * stat(session)
26 * open(blob)
27 * close(session)
28 * writemeta(session)
29 * write(session)
30 * read(session)
31 *
32 * Testing canHandleBlob is uninteresting in this state. Getting the BlobIDs
33 * will inform what canHandleBlob will return.
34 */
35class FirmwareHandlerUploadInProgressTest : public IpmiOnlyFirmwareStaticTest
36{
37};
38
39TEST_F(FirmwareHandlerUploadInProgressTest, GetBlobIdsVerifyOutputActiveImage)
40{
41 /* Opening the image file will add the active image blob id */
42 std::uint16_t flags =
43 blobs::OpenFlags::write | FirmwareBlobHandler::UpdateFlags::ipmi;
44 auto realHandler = dynamic_cast<FirmwareBlobHandler*>(handler.get());
45
46 EXPECT_CALL(imageMock, open(staticLayoutBlobId)).WillOnce(Return(true));
47
48 EXPECT_TRUE(handler->open(1, flags, staticLayoutBlobId));
49 EXPECT_EQ(FirmwareBlobHandler::UpdateState::uploadInProgress,
50 realHandler->getCurrentState());
51
52 std::vector<std::string> expectedAfterImage = {
53 staticLayoutBlobId, hashBlobId, verifyBlobId, activeImageBlobId};
54 EXPECT_THAT(handler->getBlobIds(),
55 UnorderedElementsAreArray(expectedAfterImage));
56}
57
58TEST_F(FirmwareHandlerUploadInProgressTest, GetBlobIdsVerifyOutputActiveHash)
59{
60 /* Opening the image file will add the active image blob id */
61 std::uint16_t flags =
62 blobs::OpenFlags::write | FirmwareBlobHandler::UpdateFlags::ipmi;
63 auto realHandler = dynamic_cast<FirmwareBlobHandler*>(handler.get());
64
65 EXPECT_CALL(imageMock, open(hashBlobId)).WillOnce(Return(true));
66
67 EXPECT_TRUE(handler->open(1, flags, hashBlobId));
68 EXPECT_EQ(FirmwareBlobHandler::UpdateState::uploadInProgress,
69 realHandler->getCurrentState());
70
71 std::vector<std::string> expectedAfterImage = {
72 staticLayoutBlobId, hashBlobId, verifyBlobId, activeHashBlobId};
73 EXPECT_THAT(handler->getBlobIds(),
74 UnorderedElementsAreArray(expectedAfterImage));
75}
76
Patrick Venture6f729782019-05-23 11:16:13 -070077/* TODO: Try deleting some blobs -- in this state it will depend on what the
78 * blob id is, but it's not yet implemented
79 */
80
Patrick Venture41205cc2019-05-23 11:43:43 -070081/*
82 * stat(blob)
83 */
84TEST_F(FirmwareHandlerUploadInProgressTest, StatOnActiveImageReturnsFailure)
85{
86 /* you cannot call stat() on the active image or the active hash or the
87 * verify blob.
88 */
89 std::uint16_t flags =
90 blobs::OpenFlags::write | FirmwareBlobHandler::UpdateFlags::ipmi;
91 auto realHandler = dynamic_cast<FirmwareBlobHandler*>(handler.get());
92
93 EXPECT_CALL(imageMock, open(staticLayoutBlobId)).WillOnce(Return(true));
94
95 EXPECT_TRUE(handler->open(1, flags, staticLayoutBlobId));
96 EXPECT_EQ(FirmwareBlobHandler::UpdateState::uploadInProgress,
97 realHandler->getCurrentState());
98
Patrick Venture41205cc2019-05-23 11:43:43 -070099 blobs::BlobMeta meta;
100 EXPECT_FALSE(handler->stat(activeImageBlobId, &meta));
101}
102
103TEST_F(FirmwareHandlerUploadInProgressTest, StatOnActiveHashReturnsFailure)
104{
105 /* this test is separate from the active image one so that the state doesn't
106 * change from close.
107 */
108 std::uint16_t flags =
109 blobs::OpenFlags::write | FirmwareBlobHandler::UpdateFlags::ipmi;
110 auto realHandler = dynamic_cast<FirmwareBlobHandler*>(handler.get());
111
112 EXPECT_CALL(imageMock, open(hashBlobId)).WillOnce(Return(true));
113
114 EXPECT_TRUE(handler->open(1, flags, hashBlobId));
115 EXPECT_EQ(FirmwareBlobHandler::UpdateState::uploadInProgress,
116 realHandler->getCurrentState());
117
Patrick Venture41205cc2019-05-23 11:43:43 -0700118 blobs::BlobMeta meta;
119 EXPECT_FALSE(handler->stat(activeHashBlobId, &meta));
120}
121
122TEST_F(FirmwareHandlerUploadInProgressTest, StatOnNormalBlobsReturnsSuccess)
123{
124 /* Calling stat() on the normal blobs (not the active) ones will work and
125 * return the same information as in the notYetStarted state.
126 */
127 blobs::BlobMeta expected;
128 expected.blobState = FirmwareBlobHandler::UpdateFlags::ipmi;
129 expected.size = 0;
130
131 std::uint16_t flags =
132 blobs::OpenFlags::write | FirmwareBlobHandler::UpdateFlags::ipmi;
133 auto realHandler = dynamic_cast<FirmwareBlobHandler*>(handler.get());
134
135 EXPECT_CALL(imageMock, open(staticLayoutBlobId)).WillOnce(Return(true));
136
137 EXPECT_TRUE(handler->open(1, flags, staticLayoutBlobId));
138 EXPECT_EQ(FirmwareBlobHandler::UpdateState::uploadInProgress,
139 realHandler->getCurrentState());
140
141 std::vector<std::string> testBlobs = {staticLayoutBlobId, hashBlobId};
142 for (const auto& blob : testBlobs)
143 {
144 blobs::BlobMeta meta = {};
145 EXPECT_TRUE(handler->stat(blob, &meta));
146 EXPECT_EQ(expected, meta);
147 }
148}
149
150/* TODO: stat(verifyblobid) only should exist once both /image and /hash have
151 * closed, so add this test when this is the case. NOTE: /image or /tarball
152 * should have the same effect.
153 */
154
155/*
156 * stat(session)
Patrick Ventureefc366e2019-05-23 12:00:21 -0700157 */
158TEST_F(FirmwareHandlerUploadInProgressTest,
159 CallingStatOnActiveImageOrHashSessionReturnsDetails)
160{
161 /* This test will verify that the underlying image handler is called with
162 * this stat, in addition to the normal information.
163 */
164 std::uint16_t session = 1;
165 std::uint16_t flags =
166 blobs::OpenFlags::write | FirmwareBlobHandler::UpdateFlags::ipmi;
167 auto realHandler = dynamic_cast<FirmwareBlobHandler*>(handler.get());
168
169 EXPECT_CALL(imageMock, open(staticLayoutBlobId)).WillOnce(Return(true));
170
171 EXPECT_TRUE(handler->open(session, flags, staticLayoutBlobId));
172 EXPECT_EQ(FirmwareBlobHandler::UpdateState::uploadInProgress,
173 realHandler->getCurrentState());
174
175 EXPECT_CALL(imageMock, getSize()).WillOnce(Return(32));
176
177 blobs::BlobMeta meta, expectedMeta = {};
178 expectedMeta.size = 32;
179 expectedMeta.blobState =
180 blobs::OpenFlags::write | FirmwareBlobHandler::UpdateFlags::ipmi;
181 EXPECT_TRUE(handler->stat(session, &meta));
182 EXPECT_EQ(expectedMeta, meta);
183}
184
185/*
Patrick Venture5788dbb2019-05-23 12:25:42 -0700186 * open(blob) - While any blob is open, all other fail.
187 */
188TEST_F(FirmwareHandlerUploadInProgressTest, OpeningHashFileWhileImageOpenFails)
189{
190 /* To be in this state, something must be open (and specifically either an
191 * active image (or tarball) or the hash file. Also verifies you can't just
192 * re-open the currently open file.
193 */
194 std::uint16_t flags =
195 blobs::OpenFlags::write | FirmwareBlobHandler::UpdateFlags::ipmi;
196 auto realHandler = dynamic_cast<FirmwareBlobHandler*>(handler.get());
197
198 EXPECT_CALL(imageMock, open(staticLayoutBlobId)).WillOnce(Return(true));
199
200 EXPECT_TRUE(handler->open(1, flags, staticLayoutBlobId));
201 EXPECT_EQ(FirmwareBlobHandler::UpdateState::uploadInProgress,
202 realHandler->getCurrentState());
203
204 std::vector<std::string> blobsToTry = {
205 hashBlobId, activeImageBlobId, activeHashBlobId, staticLayoutBlobId};
206 for (const auto& blob : blobsToTry)
207 {
208 EXPECT_FALSE(handler->open(2, flags, blob));
209 }
210}
211
212TEST_F(FirmwareHandlerUploadInProgressTest, OpeningImageFileWhileHashOpenFails)
213{
214 std::uint16_t flags =
215 blobs::OpenFlags::write | FirmwareBlobHandler::UpdateFlags::ipmi;
216 auto realHandler = dynamic_cast<FirmwareBlobHandler*>(handler.get());
217
218 EXPECT_CALL(imageMock, open(hashBlobId)).WillOnce(Return(true));
219
220 EXPECT_TRUE(handler->open(1, flags, hashBlobId));
221 EXPECT_EQ(FirmwareBlobHandler::UpdateState::uploadInProgress,
222 realHandler->getCurrentState());
223
224 std::vector<std::string> blobsToTry = {
225 hashBlobId, activeImageBlobId, activeHashBlobId, staticLayoutBlobId};
226 for (const auto& blob : blobsToTry)
227 {
228 EXPECT_FALSE(handler->open(2, flags, blob));
229 }
230}
231
232/*
Patrick Venture79b44742019-05-23 12:36:11 -0700233 * close(session) - closing the hash or image will trigger a state transition to
234 * verificationPending.
235 * TODO: This state transition should add the verifyBlobId. This will test that
236 * it's there, but this test doesn't verify that it only just now appeared.
237 *
238 * NOTE: Re-opening /flash/image will transition back to uploadInProgress, but
239 * that is verified in the verificationPending::open tests.
240 */
241TEST_F(FirmwareHandlerUploadInProgressTest,
242 ClosingImageFileTransitionsToVerificationPending)
243{
244 std::uint16_t flags =
245 blobs::OpenFlags::write | FirmwareBlobHandler::UpdateFlags::ipmi;
246 auto realHandler = dynamic_cast<FirmwareBlobHandler*>(handler.get());
247
248 /* TODO: uncomment this when verify is properly added. */
249 // EXPECT_FALSE(handler->canHandleBlob(verifyBlobId));
250
251 EXPECT_CALL(imageMock, open(staticLayoutBlobId)).WillOnce(Return(true));
252
253 EXPECT_TRUE(handler->open(1, flags, staticLayoutBlobId));
254 EXPECT_EQ(FirmwareBlobHandler::UpdateState::uploadInProgress,
255 realHandler->getCurrentState());
256
257 handler->close(1);
258 EXPECT_EQ(FirmwareBlobHandler::UpdateState::verificationPending,
259 realHandler->getCurrentState());
260
261 EXPECT_TRUE(handler->canHandleBlob(verifyBlobId));
262}
263
264TEST_F(FirmwareHandlerUploadInProgressTest,
265 ClosingHashFileTransitionsToVerificationPending)
266{
267 std::uint16_t flags =
268 blobs::OpenFlags::write | FirmwareBlobHandler::UpdateFlags::ipmi;
269 auto realHandler = dynamic_cast<FirmwareBlobHandler*>(handler.get());
270
271 /* TODO: uncomment this when verify is properly added. */
272 // EXPECT_FALSE(handler->canHandleBlob(verifyBlobId));
273
274 EXPECT_CALL(imageMock, open(hashBlobId)).WillOnce(Return(true));
275
276 EXPECT_TRUE(handler->open(1, flags, hashBlobId));
277 EXPECT_EQ(FirmwareBlobHandler::UpdateState::uploadInProgress,
278 realHandler->getCurrentState());
279
280 handler->close(1);
281 EXPECT_EQ(FirmwareBlobHandler::UpdateState::verificationPending,
282 realHandler->getCurrentState());
283
284 EXPECT_TRUE(handler->canHandleBlob(verifyBlobId));
285}
286
287/*
Patrick Venture41205cc2019-05-23 11:43:43 -0700288 * writemeta(session)
Patrick Venture7cf44402019-05-23 13:01:47 -0700289 */
290TEST_F(FirmwareHandlerUploadInProgressTest, WriteMetaAgainstImageReturnsSuccess)
291{
292 /* Calling write/read/writeMeta are uninteresting against the open blob in
293 * this case because the blob will just pass the call along. Whereas
294 * calling against the verify or update blob may be more interesting.
295 */
296 std::uint16_t flags =
297 blobs::OpenFlags::write | FirmwareBlobHandler::UpdateFlags::ipmi;
298 auto realHandler = dynamic_cast<FirmwareBlobHandler*>(handler.get());
299
300 EXPECT_CALL(imageMock, open(staticLayoutBlobId)).WillOnce(Return(true));
301
302 EXPECT_TRUE(handler->open(1, flags, staticLayoutBlobId));
303 EXPECT_EQ(FirmwareBlobHandler::UpdateState::uploadInProgress,
304 realHandler->getCurrentState());
305
306 /* Note: with IPMI as the transport there's no data handler, so this should
307 * fail nicely. */
308 std::vector<std::uint8_t> bytes = {0x01, 0x02};
309 EXPECT_FALSE(handler->writeMeta(1, 0, bytes));
310}
311
312/*
Patrick Venture41205cc2019-05-23 11:43:43 -0700313 * write(session)
314 * read(session)
315 */
316
Patrick Ventureebcc5222019-05-23 10:36:40 -0700317} // namespace
318} // namespace ipmi_flash