blob: 691a8a666cb87a92117d01c2b4d6d4e6cb5b193d [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
Patrick Venture615123a2019-05-23 17:20:07 -07009#include <cstdint>
10#include <string>
11#include <vector>
12
Patrick Ventureebcc5222019-05-23 10:36:40 -070013#include <gtest/gtest.h>
14
15namespace ipmi_flash
16{
17namespace
18{
19
Patrick Venture615123a2019-05-23 17:20:07 -070020using ::testing::ContainerEq;
Patrick Venture8326d072019-05-23 17:45:42 -070021using ::testing::IsEmpty;
Patrick Ventureebcc5222019-05-23 10:36:40 -070022using ::testing::Return;
23using ::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)
Patrick Venture547fa3a2019-05-23 16:06:37 -070037 * commit(session)
Patrick Ventureebcc5222019-05-23 10:36:40 -070038 *
39 * Testing canHandleBlob is uninteresting in this state. Getting the BlobIDs
40 * will inform what canHandleBlob will return.
41 */
42class FirmwareHandlerUploadInProgressTest : public IpmiOnlyFirmwareStaticTest
43{
Patrick Venturebe0fb5e2019-05-23 16:14:20 -070044 protected:
45 void openToInProgress(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 }
53
54 std::uint16_t session = 1;
55 std::uint16_t flags =
56 blobs::OpenFlags::write | FirmwareBlobHandler::UpdateFlags::ipmi;
Patrick Ventureebcc5222019-05-23 10:36:40 -070057};
58
59TEST_F(FirmwareHandlerUploadInProgressTest, GetBlobIdsVerifyOutputActiveImage)
60{
61 /* Opening the image file will add the active image blob id */
Patrick Venturebe0fb5e2019-05-23 16:14:20 -070062 openToInProgress(staticLayoutBlobId);
Patrick Ventureebcc5222019-05-23 10:36:40 -070063
64 std::vector<std::string> expectedAfterImage = {
65 staticLayoutBlobId, hashBlobId, verifyBlobId, activeImageBlobId};
66 EXPECT_THAT(handler->getBlobIds(),
67 UnorderedElementsAreArray(expectedAfterImage));
68}
69
70TEST_F(FirmwareHandlerUploadInProgressTest, GetBlobIdsVerifyOutputActiveHash)
71{
72 /* Opening the image file will add the active image blob id */
Patrick Venturebe0fb5e2019-05-23 16:14:20 -070073 openToInProgress(hashBlobId);
Patrick Ventureebcc5222019-05-23 10:36:40 -070074
75 std::vector<std::string> expectedAfterImage = {
76 staticLayoutBlobId, hashBlobId, verifyBlobId, activeHashBlobId};
77 EXPECT_THAT(handler->getBlobIds(),
78 UnorderedElementsAreArray(expectedAfterImage));
79}
80
Patrick Venture6f729782019-05-23 11:16:13 -070081/* TODO: Try deleting some blobs -- in this state it will depend on what the
82 * blob id is, but it's not yet implemented
83 */
84
Patrick Venture41205cc2019-05-23 11:43:43 -070085/*
86 * stat(blob)
87 */
88TEST_F(FirmwareHandlerUploadInProgressTest, StatOnActiveImageReturnsFailure)
89{
90 /* you cannot call stat() on the active image or the active hash or the
91 * verify blob.
92 */
Patrick Venturebe0fb5e2019-05-23 16:14:20 -070093 openToInProgress(staticLayoutBlobId);
Patrick Venture41205cc2019-05-23 11:43:43 -070094
Patrick Venture41205cc2019-05-23 11:43:43 -070095 blobs::BlobMeta meta;
96 EXPECT_FALSE(handler->stat(activeImageBlobId, &meta));
97}
98
99TEST_F(FirmwareHandlerUploadInProgressTest, StatOnActiveHashReturnsFailure)
100{
101 /* this test is separate from the active image one so that the state doesn't
102 * change from close.
103 */
Patrick Venturebe0fb5e2019-05-23 16:14:20 -0700104 openToInProgress(hashBlobId);
Patrick Venture41205cc2019-05-23 11:43:43 -0700105
Patrick Venture41205cc2019-05-23 11:43:43 -0700106 blobs::BlobMeta meta;
107 EXPECT_FALSE(handler->stat(activeHashBlobId, &meta));
108}
109
110TEST_F(FirmwareHandlerUploadInProgressTest, StatOnNormalBlobsReturnsSuccess)
111{
112 /* Calling stat() on the normal blobs (not the active) ones will work and
113 * return the same information as in the notYetStarted state.
114 */
115 blobs::BlobMeta expected;
116 expected.blobState = FirmwareBlobHandler::UpdateFlags::ipmi;
117 expected.size = 0;
118
Patrick Venturebe0fb5e2019-05-23 16:14:20 -0700119 openToInProgress(staticLayoutBlobId);
Patrick Venture41205cc2019-05-23 11:43:43 -0700120
121 std::vector<std::string> testBlobs = {staticLayoutBlobId, hashBlobId};
122 for (const auto& blob : testBlobs)
123 {
124 blobs::BlobMeta meta = {};
125 EXPECT_TRUE(handler->stat(blob, &meta));
126 EXPECT_EQ(expected, meta);
127 }
128}
129
130/* TODO: stat(verifyblobid) only should exist once both /image and /hash have
131 * closed, so add this test when this is the case. NOTE: /image or /tarball
132 * should have the same effect.
133 */
134
135/*
136 * stat(session)
Patrick Ventureefc366e2019-05-23 12:00:21 -0700137 */
138TEST_F(FirmwareHandlerUploadInProgressTest,
139 CallingStatOnActiveImageOrHashSessionReturnsDetails)
140{
141 /* This test will verify that the underlying image handler is called with
142 * this stat, in addition to the normal information.
143 */
Patrick Venturebe0fb5e2019-05-23 16:14:20 -0700144 openToInProgress(staticLayoutBlobId);
Patrick Ventureefc366e2019-05-23 12:00:21 -0700145
146 EXPECT_CALL(imageMock, getSize()).WillOnce(Return(32));
147
148 blobs::BlobMeta meta, expectedMeta = {};
149 expectedMeta.size = 32;
150 expectedMeta.blobState =
151 blobs::OpenFlags::write | FirmwareBlobHandler::UpdateFlags::ipmi;
152 EXPECT_TRUE(handler->stat(session, &meta));
153 EXPECT_EQ(expectedMeta, meta);
154}
155
156/*
Patrick Venture5788dbb2019-05-23 12:25:42 -0700157 * open(blob) - While any blob is open, all other fail.
158 */
159TEST_F(FirmwareHandlerUploadInProgressTest, OpeningHashFileWhileImageOpenFails)
160{
161 /* To be in this state, something must be open (and specifically either an
162 * active image (or tarball) or the hash file. Also verifies you can't just
163 * re-open the currently open file.
164 */
Patrick Venturebe0fb5e2019-05-23 16:14:20 -0700165 openToInProgress(staticLayoutBlobId);
Patrick Venture5788dbb2019-05-23 12:25:42 -0700166
167 std::vector<std::string> blobsToTry = {
168 hashBlobId, activeImageBlobId, activeHashBlobId, staticLayoutBlobId};
169 for (const auto& blob : blobsToTry)
170 {
171 EXPECT_FALSE(handler->open(2, flags, blob));
172 }
173}
174
175TEST_F(FirmwareHandlerUploadInProgressTest, OpeningImageFileWhileHashOpenFails)
176{
Patrick Venturebe0fb5e2019-05-23 16:14:20 -0700177 openToInProgress(hashBlobId);
Patrick Venture5788dbb2019-05-23 12:25:42 -0700178
179 std::vector<std::string> blobsToTry = {
180 hashBlobId, activeImageBlobId, activeHashBlobId, staticLayoutBlobId};
181 for (const auto& blob : blobsToTry)
182 {
183 EXPECT_FALSE(handler->open(2, flags, blob));
184 }
185}
186
187/*
Patrick Venture79b44742019-05-23 12:36:11 -0700188 * close(session) - closing the hash or image will trigger a state transition to
189 * verificationPending.
190 * TODO: This state transition should add the verifyBlobId. This will test that
191 * it's there, but this test doesn't verify that it only just now appeared.
192 *
193 * NOTE: Re-opening /flash/image will transition back to uploadInProgress, but
194 * that is verified in the verificationPending::open tests.
195 */
196TEST_F(FirmwareHandlerUploadInProgressTest,
197 ClosingImageFileTransitionsToVerificationPending)
198{
Patrick Venture79b44742019-05-23 12:36:11 -0700199 auto realHandler = dynamic_cast<FirmwareBlobHandler*>(handler.get());
200
201 /* TODO: uncomment this when verify is properly added. */
202 // EXPECT_FALSE(handler->canHandleBlob(verifyBlobId));
203
204 EXPECT_CALL(imageMock, open(staticLayoutBlobId)).WillOnce(Return(true));
205
Patrick Venturebe0fb5e2019-05-23 16:14:20 -0700206 EXPECT_TRUE(handler->open(session, flags, staticLayoutBlobId));
Patrick Venture79b44742019-05-23 12:36:11 -0700207 EXPECT_EQ(FirmwareBlobHandler::UpdateState::uploadInProgress,
208 realHandler->getCurrentState());
209
210 handler->close(1);
211 EXPECT_EQ(FirmwareBlobHandler::UpdateState::verificationPending,
212 realHandler->getCurrentState());
213
214 EXPECT_TRUE(handler->canHandleBlob(verifyBlobId));
215}
216
217TEST_F(FirmwareHandlerUploadInProgressTest,
218 ClosingHashFileTransitionsToVerificationPending)
219{
Patrick Venture79b44742019-05-23 12:36:11 -0700220 auto realHandler = dynamic_cast<FirmwareBlobHandler*>(handler.get());
221
222 /* TODO: uncomment this when verify is properly added. */
223 // EXPECT_FALSE(handler->canHandleBlob(verifyBlobId));
224
225 EXPECT_CALL(imageMock, open(hashBlobId)).WillOnce(Return(true));
226
Patrick Venturebe0fb5e2019-05-23 16:14:20 -0700227 EXPECT_TRUE(handler->open(session, flags, hashBlobId));
Patrick Venture79b44742019-05-23 12:36:11 -0700228 EXPECT_EQ(FirmwareBlobHandler::UpdateState::uploadInProgress,
229 realHandler->getCurrentState());
230
231 handler->close(1);
232 EXPECT_EQ(FirmwareBlobHandler::UpdateState::verificationPending,
233 realHandler->getCurrentState());
234
235 EXPECT_TRUE(handler->canHandleBlob(verifyBlobId));
236}
237
238/*
Patrick Venture41205cc2019-05-23 11:43:43 -0700239 * writemeta(session)
Patrick Venture7cf44402019-05-23 13:01:47 -0700240 */
Patrick Venture31eefd42019-05-23 20:27:41 -0700241TEST_F(FirmwareHandlerUploadInProgressTest,
242 WriteMetaAgainstImageReturnsFailureIfNoDataHandler)
Patrick Venture7cf44402019-05-23 13:01:47 -0700243{
244 /* Calling write/read/writeMeta are uninteresting against the open blob in
245 * this case because the blob will just pass the call along. Whereas
246 * calling against the verify or update blob may be more interesting.
247 */
Patrick Venturebe0fb5e2019-05-23 16:14:20 -0700248 openToInProgress(staticLayoutBlobId);
Patrick Venture7cf44402019-05-23 13:01:47 -0700249
Patrick Venture31eefd42019-05-23 20:27:41 -0700250 /* TODO: Consider adding a test that has a data handler, but that test
251 * already exists under the general writeMeta test suite.
252 */
Patrick Venture7cf44402019-05-23 13:01:47 -0700253 /* Note: with IPMI as the transport there's no data handler, so this should
254 * fail nicely. */
255 std::vector<std::uint8_t> bytes = {0x01, 0x02};
Patrick Venturebe0fb5e2019-05-23 16:14:20 -0700256 EXPECT_FALSE(handler->writeMeta(session, 0, bytes));
Patrick Venture7cf44402019-05-23 13:01:47 -0700257}
258
259/*
Patrick Venture41205cc2019-05-23 11:43:43 -0700260 * write(session)
Patrick Venture615123a2019-05-23 17:20:07 -0700261 */
262TEST_F(FirmwareHandlerUploadInProgressTest, WriteToImageReturnsSuccess)
263{
264 openToInProgress(staticLayoutBlobId);
265 std::vector<std::uint8_t> bytes = {0x01, 0x02};
266 EXPECT_CALL(imageMock, write(0, ContainerEq(bytes))).WillOnce(Return(true));
267 EXPECT_TRUE(handler->write(session, 0, bytes));
268}
269
270TEST_F(FirmwareHandlerUploadInProgressTest, WriteToHashReturnsSuccess)
271{
272 openToInProgress(hashBlobId);
273 std::vector<std::uint8_t> bytes = {0x01, 0x02};
274 EXPECT_CALL(imageMock, write(0, ContainerEq(bytes))).WillOnce(Return(true));
275 EXPECT_TRUE(handler->write(session, 0, bytes));
276}
277
278/*
Patrick Venture41205cc2019-05-23 11:43:43 -0700279 * read(session)
Patrick Venture615123a2019-05-23 17:20:07 -0700280 */
Patrick Venture8326d072019-05-23 17:45:42 -0700281TEST_F(FirmwareHandlerUploadInProgressTest, ReadImageFileReturnsFailure)
282{
283 /* Read is not supported. */
284 openToInProgress(staticLayoutBlobId);
285 EXPECT_THAT(handler->read(session, 0, 32), IsEmpty());
286}
Patrick Venture615123a2019-05-23 17:20:07 -0700287
288/*
Patrick Venturebe0fb5e2019-05-23 16:14:20 -0700289 * commit(session)
Patrick Venture41205cc2019-05-23 11:43:43 -0700290 */
Patrick Venture1fca1902019-05-23 17:54:18 -0700291TEST_F(FirmwareHandlerUploadInProgressTest,
292 CommitAgainstImageFileReturnsFailure)
293{
294 /* Commit is only valid against specific blobs. */
295 openToInProgress(staticLayoutBlobId);
296 EXPECT_FALSE(handler->commit(session, {}));
297}
298
299TEST_F(FirmwareHandlerUploadInProgressTest, CommitAgainstHashFileReturnsFailure)
300{
301 openToInProgress(hashBlobId);
302 EXPECT_FALSE(handler->commit(session, {}));
303}
Patrick Venture41205cc2019-05-23 11:43:43 -0700304
Patrick Ventureebcc5222019-05-23 10:36:40 -0700305} // namespace
306} // namespace ipmi_flash