blob: c1a27fe6f344160069e03f5b1a42e340016b84af [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"
Patrick Venture4b1b0452020-09-30 13:40:53 -07008#include "util.hpp"
Patrick Ventureebcc5222019-05-23 10:36:40 -07009
Patrick Venture615123a2019-05-23 17:20:07 -070010#include <cstdint>
11#include <string>
12#include <vector>
13
Patrick Ventureebcc5222019-05-23 10:36:40 -070014#include <gtest/gtest.h>
15
16namespace ipmi_flash
17{
18namespace
19{
20
Patrick Venture615123a2019-05-23 17:20:07 -070021using ::testing::ContainerEq;
Patrick Venture8326d072019-05-23 17:45:42 -070022using ::testing::IsEmpty;
Patrick Ventureebcc5222019-05-23 10:36:40 -070023using ::testing::Return;
24using ::testing::UnorderedElementsAreArray;
25
26/*
27 * There are the following calls (parameters may vary):
28 * canHandleBlob(blob)
29 * getBlobIds
30 * deleteBlob(blob)
31 * stat(blob)
32 * stat(session)
33 * open(blob)
34 * close(session)
35 * writemeta(session)
36 * write(session)
37 * read(session)
Patrick Venture547fa3a2019-05-23 16:06:37 -070038 * commit(session)
Patrick Ventureebcc5222019-05-23 10:36:40 -070039 *
40 * Testing canHandleBlob is uninteresting in this state. Getting the BlobIDs
41 * will inform what canHandleBlob will return.
42 */
43class FirmwareHandlerUploadInProgressTest : public IpmiOnlyFirmwareStaticTest
Patrick Venture9b37b092020-05-28 20:58:57 -070044{};
Patrick Ventureebcc5222019-05-23 10:36:40 -070045
46TEST_F(FirmwareHandlerUploadInProgressTest, GetBlobIdsVerifyOutputActiveImage)
47{
48 /* Opening the image file will add the active image blob id */
Patrick Venturebe0fb5e2019-05-23 16:14:20 -070049 openToInProgress(staticLayoutBlobId);
Patrick Ventureebcc5222019-05-23 10:36:40 -070050
Patrick Ventureebcc5222019-05-23 10:36:40 -070051 EXPECT_THAT(handler->getBlobIds(),
Patrick Venture9a69f732019-06-17 14:05:13 -070052 UnorderedElementsAreArray(
53 {staticLayoutBlobId, hashBlobId, activeImageBlobId}));
Patrick Ventureebcc5222019-05-23 10:36:40 -070054}
55
56TEST_F(FirmwareHandlerUploadInProgressTest, GetBlobIdsVerifyOutputActiveHash)
57{
58 /* Opening the image file will add the active image blob id */
Patrick Venturebe0fb5e2019-05-23 16:14:20 -070059 openToInProgress(hashBlobId);
Patrick Ventureebcc5222019-05-23 10:36:40 -070060
Patrick Ventureebcc5222019-05-23 10:36:40 -070061 EXPECT_THAT(handler->getBlobIds(),
Patrick Venture9a69f732019-06-17 14:05:13 -070062 UnorderedElementsAreArray(
63 {staticLayoutBlobId, hashBlobId, activeHashBlobId}));
Patrick Ventureebcc5222019-05-23 10:36:40 -070064}
65
Patrick Venture41205cc2019-05-23 11:43:43 -070066/*
67 * stat(blob)
68 */
69TEST_F(FirmwareHandlerUploadInProgressTest, StatOnActiveImageReturnsFailure)
70{
71 /* you cannot call stat() on the active image or the active hash or the
72 * verify blob.
73 */
Patrick Venturebe0fb5e2019-05-23 16:14:20 -070074 openToInProgress(staticLayoutBlobId);
Patrick Venture930c7b72019-05-24 11:11:08 -070075 ASSERT_TRUE(handler->canHandleBlob(activeImageBlobId));
Patrick Venture41205cc2019-05-23 11:43:43 -070076
Patrick Venture41205cc2019-05-23 11:43:43 -070077 blobs::BlobMeta meta;
78 EXPECT_FALSE(handler->stat(activeImageBlobId, &meta));
79}
80
81TEST_F(FirmwareHandlerUploadInProgressTest, StatOnActiveHashReturnsFailure)
82{
83 /* this test is separate from the active image one so that the state doesn't
84 * change from close.
85 */
Patrick Venturebe0fb5e2019-05-23 16:14:20 -070086 openToInProgress(hashBlobId);
Patrick Venture930c7b72019-05-24 11:11:08 -070087 ASSERT_TRUE(handler->canHandleBlob(activeHashBlobId));
Patrick Venture41205cc2019-05-23 11:43:43 -070088
Patrick Venture41205cc2019-05-23 11:43:43 -070089 blobs::BlobMeta meta;
90 EXPECT_FALSE(handler->stat(activeHashBlobId, &meta));
91}
92
93TEST_F(FirmwareHandlerUploadInProgressTest, StatOnNormalBlobsReturnsSuccess)
94{
95 /* Calling stat() on the normal blobs (not the active) ones will work and
96 * return the same information as in the notYetStarted state.
97 */
Patrick Venturebe0fb5e2019-05-23 16:14:20 -070098 openToInProgress(staticLayoutBlobId);
Patrick Venture41205cc2019-05-23 11:43:43 -070099
100 std::vector<std::string> testBlobs = {staticLayoutBlobId, hashBlobId};
101 for (const auto& blob : testBlobs)
102 {
103 blobs::BlobMeta meta = {};
104 EXPECT_TRUE(handler->stat(blob, &meta));
Benjamin Fair12901982019-11-12 13:55:46 -0800105 EXPECT_EQ(expectedIdleMeta, meta);
Patrick Venture41205cc2019-05-23 11:43:43 -0700106 }
107}
108
Patrick Venture41205cc2019-05-23 11:43:43 -0700109/*
110 * stat(session)
Patrick Ventureefc366e2019-05-23 12:00:21 -0700111 */
112TEST_F(FirmwareHandlerUploadInProgressTest,
113 CallingStatOnActiveImageOrHashSessionReturnsDetails)
114{
115 /* This test will verify that the underlying image handler is called with
116 * this stat, in addition to the normal information.
117 */
Patrick Venturebe0fb5e2019-05-23 16:14:20 -0700118 openToInProgress(staticLayoutBlobId);
Patrick Ventureefc366e2019-05-23 12:00:21 -0700119
Patrick Ventured4e20de2019-07-18 12:48:05 -0700120 EXPECT_CALL(*imageMock2, getSize()).WillOnce(Return(32));
Patrick Ventureefc366e2019-05-23 12:00:21 -0700121
122 blobs::BlobMeta meta, expectedMeta = {};
123 expectedMeta.size = 32;
124 expectedMeta.blobState =
Patrick Venture84778b82019-06-26 20:11:09 -0700125 blobs::OpenFlags::write | FirmwareFlags::UpdateFlags::ipmi;
Patrick Ventureefc366e2019-05-23 12:00:21 -0700126 EXPECT_TRUE(handler->stat(session, &meta));
127 EXPECT_EQ(expectedMeta, meta);
128}
129
130/*
Patrick Venture5788dbb2019-05-23 12:25:42 -0700131 * open(blob) - While any blob is open, all other fail.
Patrick Venture072a7dd2019-05-28 13:51:26 -0700132 *
133 * The fullBlobsList is all the blob_ids present if both /flash/image and
134 * /flash/hash are opened, and one is left open (so there's no verify blob). if
135 * left closed, we'd be in verificationPending, not uploadInProgress.
Patrick Venture5788dbb2019-05-23 12:25:42 -0700136 */
Patrick Venture072a7dd2019-05-28 13:51:26 -0700137const std::vector<std::string> fullBlobsList = {
138 activeHashBlobId, activeImageBlobId, hashBlobId, staticLayoutBlobId};
139
Patrick Venture5788dbb2019-05-23 12:25:42 -0700140TEST_F(FirmwareHandlerUploadInProgressTest, OpeningHashFileWhileImageOpenFails)
141{
142 /* To be in this state, something must be open (and specifically either an
143 * active image (or tarball) or the hash file. Also verifies you can't just
144 * re-open the currently open file.
145 */
Patrick Venturebe0fb5e2019-05-23 16:14:20 -0700146 openToInProgress(staticLayoutBlobId);
Patrick Venture5788dbb2019-05-23 12:25:42 -0700147
Patrick Venture072a7dd2019-05-28 13:51:26 -0700148 for (const auto& blob : fullBlobsList)
Patrick Venture5788dbb2019-05-23 12:25:42 -0700149 {
150 EXPECT_FALSE(handler->open(2, flags, blob));
151 }
152}
153
154TEST_F(FirmwareHandlerUploadInProgressTest, OpeningImageFileWhileHashOpenFails)
155{
Patrick Venturebe0fb5e2019-05-23 16:14:20 -0700156 openToInProgress(hashBlobId);
Patrick Venture5788dbb2019-05-23 12:25:42 -0700157
Patrick Venture072a7dd2019-05-28 13:51:26 -0700158 for (const auto& blob : fullBlobsList)
Patrick Venture5788dbb2019-05-23 12:25:42 -0700159 {
160 EXPECT_FALSE(handler->open(2, flags, blob));
161 }
162}
163
164/*
Patrick Venture79b44742019-05-23 12:36:11 -0700165 * close(session) - closing the hash or image will trigger a state transition to
166 * verificationPending.
Patrick Venture79b44742019-05-23 12:36:11 -0700167 *
168 * NOTE: Re-opening /flash/image will transition back to uploadInProgress, but
169 * that is verified in the verificationPending::open tests.
170 */
171TEST_F(FirmwareHandlerUploadInProgressTest,
172 ClosingImageFileTransitionsToVerificationPending)
173{
Patrick Venture930c7b72019-05-24 11:11:08 -0700174 EXPECT_FALSE(handler->canHandleBlob(verifyBlobId));
Patrick Venture6fdd02e2019-05-28 13:02:04 -0700175 openToInProgress(staticLayoutBlobId);
Patrick Venture79b44742019-05-23 12:36:11 -0700176
Patrick Venture6fdd02e2019-05-28 13:02:04 -0700177 handler->close(session);
178 expectedState(FirmwareBlobHandler::UpdateState::verificationPending);
Patrick Venture79b44742019-05-23 12:36:11 -0700179
180 EXPECT_TRUE(handler->canHandleBlob(verifyBlobId));
181}
182
183TEST_F(FirmwareHandlerUploadInProgressTest,
184 ClosingHashFileTransitionsToVerificationPending)
185{
Patrick Venture930c7b72019-05-24 11:11:08 -0700186 EXPECT_FALSE(handler->canHandleBlob(verifyBlobId));
Patrick Venture6fdd02e2019-05-28 13:02:04 -0700187 openToInProgress(hashBlobId);
Patrick Venture79b44742019-05-23 12:36:11 -0700188
Patrick Venture6fdd02e2019-05-28 13:02:04 -0700189 handler->close(session);
190 expectedState(FirmwareBlobHandler::UpdateState::verificationPending);
Patrick Venture79b44742019-05-23 12:36:11 -0700191
Patrick Venture1999eef2019-07-01 11:44:09 -0700192 EXPECT_FALSE(handler->canHandleBlob(verifyBlobId));
Patrick Venture79b44742019-05-23 12:36:11 -0700193}
194
195/*
Patrick Venture41205cc2019-05-23 11:43:43 -0700196 * writemeta(session)
Patrick Venture7cf44402019-05-23 13:01:47 -0700197 */
Patrick Venture31eefd42019-05-23 20:27:41 -0700198TEST_F(FirmwareHandlerUploadInProgressTest,
199 WriteMetaAgainstImageReturnsFailureIfNoDataHandler)
Patrick Venture7cf44402019-05-23 13:01:47 -0700200{
201 /* Calling write/read/writeMeta are uninteresting against the open blob in
202 * this case because the blob will just pass the call along. Whereas
203 * calling against the verify or update blob may be more interesting.
204 */
Patrick Venturebe0fb5e2019-05-23 16:14:20 -0700205 openToInProgress(staticLayoutBlobId);
Patrick Venture7cf44402019-05-23 13:01:47 -0700206
Patrick Venture31eefd42019-05-23 20:27:41 -0700207 /* TODO: Consider adding a test that has a data handler, but that test
208 * already exists under the general writeMeta test suite.
209 */
Patrick Venture7cf44402019-05-23 13:01:47 -0700210 /* Note: with IPMI as the transport there's no data handler, so this should
211 * fail nicely. */
212 std::vector<std::uint8_t> bytes = {0x01, 0x02};
Patrick Venturebe0fb5e2019-05-23 16:14:20 -0700213 EXPECT_FALSE(handler->writeMeta(session, 0, bytes));
Patrick Venture7cf44402019-05-23 13:01:47 -0700214}
215
216/*
Patrick Venture41205cc2019-05-23 11:43:43 -0700217 * write(session)
Patrick Venture615123a2019-05-23 17:20:07 -0700218 */
219TEST_F(FirmwareHandlerUploadInProgressTest, WriteToImageReturnsSuccess)
220{
221 openToInProgress(staticLayoutBlobId);
222 std::vector<std::uint8_t> bytes = {0x01, 0x02};
Patrick Ventured4e20de2019-07-18 12:48:05 -0700223 EXPECT_CALL(*imageMock2, write(0, ContainerEq(bytes)))
224 .WillOnce(Return(true));
Patrick Venture615123a2019-05-23 17:20:07 -0700225 EXPECT_TRUE(handler->write(session, 0, bytes));
226}
227
228TEST_F(FirmwareHandlerUploadInProgressTest, WriteToHashReturnsSuccess)
229{
230 openToInProgress(hashBlobId);
231 std::vector<std::uint8_t> bytes = {0x01, 0x02};
Patrick Ventured4e20de2019-07-18 12:48:05 -0700232 EXPECT_CALL(*hashImageMock, write(0, ContainerEq(bytes)))
233 .WillOnce(Return(true));
Patrick Venture615123a2019-05-23 17:20:07 -0700234 EXPECT_TRUE(handler->write(session, 0, bytes));
235}
236
237/*
Patrick Venture41205cc2019-05-23 11:43:43 -0700238 * read(session)
Patrick Venture615123a2019-05-23 17:20:07 -0700239 */
Patrick Venture8326d072019-05-23 17:45:42 -0700240TEST_F(FirmwareHandlerUploadInProgressTest, ReadImageFileReturnsFailure)
241{
242 /* Read is not supported. */
243 openToInProgress(staticLayoutBlobId);
244 EXPECT_THAT(handler->read(session, 0, 32), IsEmpty());
245}
Patrick Venture615123a2019-05-23 17:20:07 -0700246
247/*
Patrick Venturebe0fb5e2019-05-23 16:14:20 -0700248 * commit(session)
Patrick Venture41205cc2019-05-23 11:43:43 -0700249 */
Patrick Venture1fca1902019-05-23 17:54:18 -0700250TEST_F(FirmwareHandlerUploadInProgressTest,
251 CommitAgainstImageFileReturnsFailure)
252{
253 /* Commit is only valid against specific blobs. */
254 openToInProgress(staticLayoutBlobId);
255 EXPECT_FALSE(handler->commit(session, {}));
256}
257
258TEST_F(FirmwareHandlerUploadInProgressTest, CommitAgainstHashFileReturnsFailure)
259{
260 openToInProgress(hashBlobId);
261 EXPECT_FALSE(handler->commit(session, {}));
262}
Patrick Venture41205cc2019-05-23 11:43:43 -0700263
Patrick Venturebcc0c772019-06-17 10:42:06 -0700264/*
265 * deleteBlob(blob)
266 */
267TEST_F(FirmwareHandlerUploadInProgressTest, DeleteBlobReturnsFalse)
268{
269 /* Try deleting all blobs, it doesn't really matter which though because you
270 * cannot close out an open session, therefore you must fail to delete
271 * anything unless everything is closed.
272 */
273 openToInProgress(staticLayoutBlobId);
274 auto blobs = handler->getBlobIds();
275 for (const auto& b : blobs)
276 {
277 EXPECT_FALSE(handler->deleteBlob(b));
278 }
279}
280
Patrick Venture92f26152020-05-26 19:47:36 -0700281/*
282 * expire(session)
283 */
284TEST_F(FirmwareHandlerUploadInProgressTest, ExpireAbortsProcess)
285{
286 openToInProgress(staticLayoutBlobId);
287
288 ASSERT_TRUE(handler->expire(session));
289 EXPECT_THAT(handler->getBlobIds(),
290 UnorderedElementsAreArray(startingBlobs));
291 expectedState(FirmwareBlobHandler::UpdateState::notYetStarted);
292}
293
Patrick Ventureebcc5222019-05-23 10:36:40 -0700294} // namespace
295} // namespace ipmi_flash