blob: 237fc44b606d752dfdc5836fb9e999f29ac4955c [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 = {
Patrick Venture930c7b72019-05-24 11:11:08 -070065 staticLayoutBlobId, hashBlobId, activeImageBlobId};
Patrick Ventureebcc5222019-05-23 10:36:40 -070066 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 = {
Patrick Venture930c7b72019-05-24 11:11:08 -070076 staticLayoutBlobId, hashBlobId, activeHashBlobId};
Patrick Ventureebcc5222019-05-23 10:36:40 -070077 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 Venture930c7b72019-05-24 11:11:08 -070094 ASSERT_TRUE(handler->canHandleBlob(activeImageBlobId));
Patrick Venture41205cc2019-05-23 11:43:43 -070095
Patrick Venture41205cc2019-05-23 11:43:43 -070096 blobs::BlobMeta meta;
97 EXPECT_FALSE(handler->stat(activeImageBlobId, &meta));
98}
99
100TEST_F(FirmwareHandlerUploadInProgressTest, StatOnActiveHashReturnsFailure)
101{
102 /* this test is separate from the active image one so that the state doesn't
103 * change from close.
104 */
Patrick Venturebe0fb5e2019-05-23 16:14:20 -0700105 openToInProgress(hashBlobId);
Patrick Venture930c7b72019-05-24 11:11:08 -0700106 ASSERT_TRUE(handler->canHandleBlob(activeHashBlobId));
Patrick Venture41205cc2019-05-23 11:43:43 -0700107
Patrick Venture41205cc2019-05-23 11:43:43 -0700108 blobs::BlobMeta meta;
109 EXPECT_FALSE(handler->stat(activeHashBlobId, &meta));
110}
111
112TEST_F(FirmwareHandlerUploadInProgressTest, StatOnNormalBlobsReturnsSuccess)
113{
114 /* Calling stat() on the normal blobs (not the active) ones will work and
115 * return the same information as in the notYetStarted state.
116 */
117 blobs::BlobMeta expected;
118 expected.blobState = FirmwareBlobHandler::UpdateFlags::ipmi;
119 expected.size = 0;
120
Patrick Venturebe0fb5e2019-05-23 16:14:20 -0700121 openToInProgress(staticLayoutBlobId);
Patrick Venture41205cc2019-05-23 11:43:43 -0700122
123 std::vector<std::string> testBlobs = {staticLayoutBlobId, hashBlobId};
124 for (const auto& blob : testBlobs)
125 {
126 blobs::BlobMeta meta = {};
127 EXPECT_TRUE(handler->stat(blob, &meta));
128 EXPECT_EQ(expected, meta);
129 }
130}
131
Patrick Venture41205cc2019-05-23 11:43:43 -0700132/*
133 * stat(session)
Patrick Ventureefc366e2019-05-23 12:00:21 -0700134 */
135TEST_F(FirmwareHandlerUploadInProgressTest,
136 CallingStatOnActiveImageOrHashSessionReturnsDetails)
137{
138 /* This test will verify that the underlying image handler is called with
139 * this stat, in addition to the normal information.
140 */
Patrick Venturebe0fb5e2019-05-23 16:14:20 -0700141 openToInProgress(staticLayoutBlobId);
Patrick Ventureefc366e2019-05-23 12:00:21 -0700142
143 EXPECT_CALL(imageMock, getSize()).WillOnce(Return(32));
144
145 blobs::BlobMeta meta, expectedMeta = {};
146 expectedMeta.size = 32;
147 expectedMeta.blobState =
148 blobs::OpenFlags::write | FirmwareBlobHandler::UpdateFlags::ipmi;
149 EXPECT_TRUE(handler->stat(session, &meta));
150 EXPECT_EQ(expectedMeta, meta);
151}
152
153/*
Patrick Venture5788dbb2019-05-23 12:25:42 -0700154 * open(blob) - While any blob is open, all other fail.
155 */
156TEST_F(FirmwareHandlerUploadInProgressTest, OpeningHashFileWhileImageOpenFails)
157{
158 /* To be in this state, something must be open (and specifically either an
159 * active image (or tarball) or the hash file. Also verifies you can't just
160 * re-open the currently open file.
161 */
Patrick Venturebe0fb5e2019-05-23 16:14:20 -0700162 openToInProgress(staticLayoutBlobId);
Patrick Venture5788dbb2019-05-23 12:25:42 -0700163
164 std::vector<std::string> blobsToTry = {
165 hashBlobId, activeImageBlobId, activeHashBlobId, staticLayoutBlobId};
166 for (const auto& blob : blobsToTry)
167 {
168 EXPECT_FALSE(handler->open(2, flags, blob));
169 }
170}
171
172TEST_F(FirmwareHandlerUploadInProgressTest, OpeningImageFileWhileHashOpenFails)
173{
Patrick Venturebe0fb5e2019-05-23 16:14:20 -0700174 openToInProgress(hashBlobId);
Patrick Venture5788dbb2019-05-23 12:25:42 -0700175
176 std::vector<std::string> blobsToTry = {
177 hashBlobId, activeImageBlobId, activeHashBlobId, staticLayoutBlobId};
178 for (const auto& blob : blobsToTry)
179 {
180 EXPECT_FALSE(handler->open(2, flags, blob));
181 }
182}
183
184/*
Patrick Venture79b44742019-05-23 12:36:11 -0700185 * close(session) - closing the hash or image will trigger a state transition to
186 * verificationPending.
Patrick Venture79b44742019-05-23 12:36:11 -0700187 *
188 * NOTE: Re-opening /flash/image will transition back to uploadInProgress, but
189 * that is verified in the verificationPending::open tests.
190 */
191TEST_F(FirmwareHandlerUploadInProgressTest,
192 ClosingImageFileTransitionsToVerificationPending)
193{
Patrick Venture79b44742019-05-23 12:36:11 -0700194 auto realHandler = dynamic_cast<FirmwareBlobHandler*>(handler.get());
195
Patrick Venture930c7b72019-05-24 11:11:08 -0700196 EXPECT_FALSE(handler->canHandleBlob(verifyBlobId));
Patrick Venture79b44742019-05-23 12:36:11 -0700197
198 EXPECT_CALL(imageMock, open(staticLayoutBlobId)).WillOnce(Return(true));
199
Patrick Venturebe0fb5e2019-05-23 16:14:20 -0700200 EXPECT_TRUE(handler->open(session, flags, staticLayoutBlobId));
Patrick Venture79b44742019-05-23 12:36:11 -0700201 EXPECT_EQ(FirmwareBlobHandler::UpdateState::uploadInProgress,
202 realHandler->getCurrentState());
203
204 handler->close(1);
205 EXPECT_EQ(FirmwareBlobHandler::UpdateState::verificationPending,
206 realHandler->getCurrentState());
207
208 EXPECT_TRUE(handler->canHandleBlob(verifyBlobId));
209}
210
211TEST_F(FirmwareHandlerUploadInProgressTest,
212 ClosingHashFileTransitionsToVerificationPending)
213{
Patrick Venture79b44742019-05-23 12:36:11 -0700214 auto realHandler = dynamic_cast<FirmwareBlobHandler*>(handler.get());
215
Patrick Venture930c7b72019-05-24 11:11:08 -0700216 EXPECT_FALSE(handler->canHandleBlob(verifyBlobId));
Patrick Venture79b44742019-05-23 12:36:11 -0700217
218 EXPECT_CALL(imageMock, open(hashBlobId)).WillOnce(Return(true));
219
Patrick Venturebe0fb5e2019-05-23 16:14:20 -0700220 EXPECT_TRUE(handler->open(session, flags, hashBlobId));
Patrick Venture79b44742019-05-23 12:36:11 -0700221 EXPECT_EQ(FirmwareBlobHandler::UpdateState::uploadInProgress,
222 realHandler->getCurrentState());
223
224 handler->close(1);
225 EXPECT_EQ(FirmwareBlobHandler::UpdateState::verificationPending,
226 realHandler->getCurrentState());
227
228 EXPECT_TRUE(handler->canHandleBlob(verifyBlobId));
229}
230
231/*
Patrick Venture41205cc2019-05-23 11:43:43 -0700232 * writemeta(session)
Patrick Venture7cf44402019-05-23 13:01:47 -0700233 */
Patrick Venture31eefd42019-05-23 20:27:41 -0700234TEST_F(FirmwareHandlerUploadInProgressTest,
235 WriteMetaAgainstImageReturnsFailureIfNoDataHandler)
Patrick Venture7cf44402019-05-23 13:01:47 -0700236{
237 /* Calling write/read/writeMeta are uninteresting against the open blob in
238 * this case because the blob will just pass the call along. Whereas
239 * calling against the verify or update blob may be more interesting.
240 */
Patrick Venturebe0fb5e2019-05-23 16:14:20 -0700241 openToInProgress(staticLayoutBlobId);
Patrick Venture7cf44402019-05-23 13:01:47 -0700242
Patrick Venture31eefd42019-05-23 20:27:41 -0700243 /* TODO: Consider adding a test that has a data handler, but that test
244 * already exists under the general writeMeta test suite.
245 */
Patrick Venture7cf44402019-05-23 13:01:47 -0700246 /* Note: with IPMI as the transport there's no data handler, so this should
247 * fail nicely. */
248 std::vector<std::uint8_t> bytes = {0x01, 0x02};
Patrick Venturebe0fb5e2019-05-23 16:14:20 -0700249 EXPECT_FALSE(handler->writeMeta(session, 0, bytes));
Patrick Venture7cf44402019-05-23 13:01:47 -0700250}
251
252/*
Patrick Venture41205cc2019-05-23 11:43:43 -0700253 * write(session)
Patrick Venture615123a2019-05-23 17:20:07 -0700254 */
255TEST_F(FirmwareHandlerUploadInProgressTest, WriteToImageReturnsSuccess)
256{
257 openToInProgress(staticLayoutBlobId);
258 std::vector<std::uint8_t> bytes = {0x01, 0x02};
259 EXPECT_CALL(imageMock, write(0, ContainerEq(bytes))).WillOnce(Return(true));
260 EXPECT_TRUE(handler->write(session, 0, bytes));
261}
262
263TEST_F(FirmwareHandlerUploadInProgressTest, WriteToHashReturnsSuccess)
264{
265 openToInProgress(hashBlobId);
266 std::vector<std::uint8_t> bytes = {0x01, 0x02};
267 EXPECT_CALL(imageMock, write(0, ContainerEq(bytes))).WillOnce(Return(true));
268 EXPECT_TRUE(handler->write(session, 0, bytes));
269}
270
271/*
Patrick Venture41205cc2019-05-23 11:43:43 -0700272 * read(session)
Patrick Venture615123a2019-05-23 17:20:07 -0700273 */
Patrick Venture8326d072019-05-23 17:45:42 -0700274TEST_F(FirmwareHandlerUploadInProgressTest, ReadImageFileReturnsFailure)
275{
276 /* Read is not supported. */
277 openToInProgress(staticLayoutBlobId);
278 EXPECT_THAT(handler->read(session, 0, 32), IsEmpty());
279}
Patrick Venture615123a2019-05-23 17:20:07 -0700280
281/*
Patrick Venturebe0fb5e2019-05-23 16:14:20 -0700282 * commit(session)
Patrick Venture41205cc2019-05-23 11:43:43 -0700283 */
Patrick Venture1fca1902019-05-23 17:54:18 -0700284TEST_F(FirmwareHandlerUploadInProgressTest,
285 CommitAgainstImageFileReturnsFailure)
286{
287 /* Commit is only valid against specific blobs. */
288 openToInProgress(staticLayoutBlobId);
289 EXPECT_FALSE(handler->commit(session, {}));
290}
291
292TEST_F(FirmwareHandlerUploadInProgressTest, CommitAgainstHashFileReturnsFailure)
293{
294 openToInProgress(hashBlobId);
295 EXPECT_FALSE(handler->commit(session, {}));
296}
Patrick Venture41205cc2019-05-23 11:43:43 -0700297
Patrick Ventureebcc5222019-05-23 10:36:40 -0700298} // namespace
299} // namespace ipmi_flash