blob: 5ed54911c1ed8f2a3507ed8bef8c298020e3123c [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{
44};
45
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
51 std::vector<std::string> expectedAfterImage = {
Patrick Venture930c7b72019-05-24 11:11:08 -070052 staticLayoutBlobId, hashBlobId, activeImageBlobId};
Patrick Ventureebcc5222019-05-23 10:36:40 -070053 EXPECT_THAT(handler->getBlobIds(),
54 UnorderedElementsAreArray(expectedAfterImage));
55}
56
57TEST_F(FirmwareHandlerUploadInProgressTest, GetBlobIdsVerifyOutputActiveHash)
58{
59 /* Opening the image file will add the active image blob id */
Patrick Venturebe0fb5e2019-05-23 16:14:20 -070060 openToInProgress(hashBlobId);
Patrick Ventureebcc5222019-05-23 10:36:40 -070061
62 std::vector<std::string> expectedAfterImage = {
Patrick Venture930c7b72019-05-24 11:11:08 -070063 staticLayoutBlobId, hashBlobId, activeHashBlobId};
Patrick Ventureebcc5222019-05-23 10:36:40 -070064 EXPECT_THAT(handler->getBlobIds(),
65 UnorderedElementsAreArray(expectedAfterImage));
66}
67
Patrick Venture6f729782019-05-23 11:16:13 -070068/* TODO: Try deleting some blobs -- in this state it will depend on what the
69 * blob id is, but it's not yet implemented
70 */
71
Patrick Venture41205cc2019-05-23 11:43:43 -070072/*
73 * stat(blob)
74 */
75TEST_F(FirmwareHandlerUploadInProgressTest, StatOnActiveImageReturnsFailure)
76{
77 /* you cannot call stat() on the active image or the active hash or the
78 * verify blob.
79 */
Patrick Venturebe0fb5e2019-05-23 16:14:20 -070080 openToInProgress(staticLayoutBlobId);
Patrick Venture930c7b72019-05-24 11:11:08 -070081 ASSERT_TRUE(handler->canHandleBlob(activeImageBlobId));
Patrick Venture41205cc2019-05-23 11:43:43 -070082
Patrick Venture41205cc2019-05-23 11:43:43 -070083 blobs::BlobMeta meta;
84 EXPECT_FALSE(handler->stat(activeImageBlobId, &meta));
85}
86
87TEST_F(FirmwareHandlerUploadInProgressTest, StatOnActiveHashReturnsFailure)
88{
89 /* this test is separate from the active image one so that the state doesn't
90 * change from close.
91 */
Patrick Venturebe0fb5e2019-05-23 16:14:20 -070092 openToInProgress(hashBlobId);
Patrick Venture930c7b72019-05-24 11:11:08 -070093 ASSERT_TRUE(handler->canHandleBlob(activeHashBlobId));
Patrick Venture41205cc2019-05-23 11:43:43 -070094
Patrick Venture41205cc2019-05-23 11:43:43 -070095 blobs::BlobMeta meta;
96 EXPECT_FALSE(handler->stat(activeHashBlobId, &meta));
97}
98
99TEST_F(FirmwareHandlerUploadInProgressTest, StatOnNormalBlobsReturnsSuccess)
100{
101 /* Calling stat() on the normal blobs (not the active) ones will work and
102 * return the same information as in the notYetStarted state.
103 */
104 blobs::BlobMeta expected;
105 expected.blobState = FirmwareBlobHandler::UpdateFlags::ipmi;
106 expected.size = 0;
107
Patrick Venturebe0fb5e2019-05-23 16:14:20 -0700108 openToInProgress(staticLayoutBlobId);
Patrick Venture41205cc2019-05-23 11:43:43 -0700109
110 std::vector<std::string> testBlobs = {staticLayoutBlobId, hashBlobId};
111 for (const auto& blob : testBlobs)
112 {
113 blobs::BlobMeta meta = {};
114 EXPECT_TRUE(handler->stat(blob, &meta));
115 EXPECT_EQ(expected, meta);
116 }
117}
118
Patrick Venture41205cc2019-05-23 11:43:43 -0700119/*
120 * stat(session)
Patrick Ventureefc366e2019-05-23 12:00:21 -0700121 */
122TEST_F(FirmwareHandlerUploadInProgressTest,
123 CallingStatOnActiveImageOrHashSessionReturnsDetails)
124{
125 /* This test will verify that the underlying image handler is called with
126 * this stat, in addition to the normal information.
127 */
Patrick Venturebe0fb5e2019-05-23 16:14:20 -0700128 openToInProgress(staticLayoutBlobId);
Patrick Ventureefc366e2019-05-23 12:00:21 -0700129
130 EXPECT_CALL(imageMock, getSize()).WillOnce(Return(32));
131
132 blobs::BlobMeta meta, expectedMeta = {};
133 expectedMeta.size = 32;
134 expectedMeta.blobState =
135 blobs::OpenFlags::write | FirmwareBlobHandler::UpdateFlags::ipmi;
136 EXPECT_TRUE(handler->stat(session, &meta));
137 EXPECT_EQ(expectedMeta, meta);
138}
139
140/*
Patrick Venture5788dbb2019-05-23 12:25:42 -0700141 * open(blob) - While any blob is open, all other fail.
Patrick Venture072a7dd2019-05-28 13:51:26 -0700142 *
143 * The fullBlobsList is all the blob_ids present if both /flash/image and
144 * /flash/hash are opened, and one is left open (so there's no verify blob). if
145 * left closed, we'd be in verificationPending, not uploadInProgress.
Patrick Venture5788dbb2019-05-23 12:25:42 -0700146 */
Patrick Venture072a7dd2019-05-28 13:51:26 -0700147const std::vector<std::string> fullBlobsList = {
148 activeHashBlobId, activeImageBlobId, hashBlobId, staticLayoutBlobId};
149
Patrick Venture5788dbb2019-05-23 12:25:42 -0700150TEST_F(FirmwareHandlerUploadInProgressTest, OpeningHashFileWhileImageOpenFails)
151{
152 /* To be in this state, something must be open (and specifically either an
153 * active image (or tarball) or the hash file. Also verifies you can't just
154 * re-open the currently open file.
155 */
Patrick Venturebe0fb5e2019-05-23 16:14:20 -0700156 openToInProgress(staticLayoutBlobId);
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
164TEST_F(FirmwareHandlerUploadInProgressTest, OpeningImageFileWhileHashOpenFails)
165{
Patrick Venturebe0fb5e2019-05-23 16:14:20 -0700166 openToInProgress(hashBlobId);
Patrick Venture5788dbb2019-05-23 12:25:42 -0700167
Patrick Venture072a7dd2019-05-28 13:51:26 -0700168 for (const auto& blob : fullBlobsList)
Patrick Venture5788dbb2019-05-23 12:25:42 -0700169 {
170 EXPECT_FALSE(handler->open(2, flags, blob));
171 }
172}
173
174/*
Patrick Venture79b44742019-05-23 12:36:11 -0700175 * close(session) - closing the hash or image will trigger a state transition to
176 * verificationPending.
Patrick Venture79b44742019-05-23 12:36:11 -0700177 *
178 * NOTE: Re-opening /flash/image will transition back to uploadInProgress, but
179 * that is verified in the verificationPending::open tests.
180 */
181TEST_F(FirmwareHandlerUploadInProgressTest,
182 ClosingImageFileTransitionsToVerificationPending)
183{
Patrick Venture930c7b72019-05-24 11:11:08 -0700184 EXPECT_FALSE(handler->canHandleBlob(verifyBlobId));
Patrick Venture6fdd02e2019-05-28 13:02:04 -0700185 openToInProgress(staticLayoutBlobId);
Patrick Venture79b44742019-05-23 12:36:11 -0700186
Patrick Venture6fdd02e2019-05-28 13:02:04 -0700187 handler->close(session);
188 expectedState(FirmwareBlobHandler::UpdateState::verificationPending);
Patrick Venture79b44742019-05-23 12:36:11 -0700189
190 EXPECT_TRUE(handler->canHandleBlob(verifyBlobId));
191}
192
193TEST_F(FirmwareHandlerUploadInProgressTest,
194 ClosingHashFileTransitionsToVerificationPending)
195{
Patrick Venture930c7b72019-05-24 11:11:08 -0700196 EXPECT_FALSE(handler->canHandleBlob(verifyBlobId));
Patrick Venture6fdd02e2019-05-28 13:02:04 -0700197 openToInProgress(hashBlobId);
Patrick Venture79b44742019-05-23 12:36:11 -0700198
Patrick Venture6fdd02e2019-05-28 13:02:04 -0700199 handler->close(session);
200 expectedState(FirmwareBlobHandler::UpdateState::verificationPending);
Patrick Venture79b44742019-05-23 12:36:11 -0700201
202 EXPECT_TRUE(handler->canHandleBlob(verifyBlobId));
203}
204
205/*
Patrick Venture41205cc2019-05-23 11:43:43 -0700206 * writemeta(session)
Patrick Venture7cf44402019-05-23 13:01:47 -0700207 */
Patrick Venture31eefd42019-05-23 20:27:41 -0700208TEST_F(FirmwareHandlerUploadInProgressTest,
209 WriteMetaAgainstImageReturnsFailureIfNoDataHandler)
Patrick Venture7cf44402019-05-23 13:01:47 -0700210{
211 /* Calling write/read/writeMeta are uninteresting against the open blob in
212 * this case because the blob will just pass the call along. Whereas
213 * calling against the verify or update blob may be more interesting.
214 */
Patrick Venturebe0fb5e2019-05-23 16:14:20 -0700215 openToInProgress(staticLayoutBlobId);
Patrick Venture7cf44402019-05-23 13:01:47 -0700216
Patrick Venture31eefd42019-05-23 20:27:41 -0700217 /* TODO: Consider adding a test that has a data handler, but that test
218 * already exists under the general writeMeta test suite.
219 */
Patrick Venture7cf44402019-05-23 13:01:47 -0700220 /* Note: with IPMI as the transport there's no data handler, so this should
221 * fail nicely. */
222 std::vector<std::uint8_t> bytes = {0x01, 0x02};
Patrick Venturebe0fb5e2019-05-23 16:14:20 -0700223 EXPECT_FALSE(handler->writeMeta(session, 0, bytes));
Patrick Venture7cf44402019-05-23 13:01:47 -0700224}
225
226/*
Patrick Venture41205cc2019-05-23 11:43:43 -0700227 * write(session)
Patrick Venture615123a2019-05-23 17:20:07 -0700228 */
229TEST_F(FirmwareHandlerUploadInProgressTest, WriteToImageReturnsSuccess)
230{
231 openToInProgress(staticLayoutBlobId);
232 std::vector<std::uint8_t> bytes = {0x01, 0x02};
233 EXPECT_CALL(imageMock, write(0, ContainerEq(bytes))).WillOnce(Return(true));
234 EXPECT_TRUE(handler->write(session, 0, bytes));
235}
236
237TEST_F(FirmwareHandlerUploadInProgressTest, WriteToHashReturnsSuccess)
238{
239 openToInProgress(hashBlobId);
240 std::vector<std::uint8_t> bytes = {0x01, 0x02};
241 EXPECT_CALL(imageMock, write(0, ContainerEq(bytes))).WillOnce(Return(true));
242 EXPECT_TRUE(handler->write(session, 0, bytes));
243}
244
245/*
Patrick Venture41205cc2019-05-23 11:43:43 -0700246 * read(session)
Patrick Venture615123a2019-05-23 17:20:07 -0700247 */
Patrick Venture8326d072019-05-23 17:45:42 -0700248TEST_F(FirmwareHandlerUploadInProgressTest, ReadImageFileReturnsFailure)
249{
250 /* Read is not supported. */
251 openToInProgress(staticLayoutBlobId);
252 EXPECT_THAT(handler->read(session, 0, 32), IsEmpty());
253}
Patrick Venture615123a2019-05-23 17:20:07 -0700254
255/*
Patrick Venturebe0fb5e2019-05-23 16:14:20 -0700256 * commit(session)
Patrick Venture41205cc2019-05-23 11:43:43 -0700257 */
Patrick Venture1fca1902019-05-23 17:54:18 -0700258TEST_F(FirmwareHandlerUploadInProgressTest,
259 CommitAgainstImageFileReturnsFailure)
260{
261 /* Commit is only valid against specific blobs. */
262 openToInProgress(staticLayoutBlobId);
263 EXPECT_FALSE(handler->commit(session, {}));
264}
265
266TEST_F(FirmwareHandlerUploadInProgressTest, CommitAgainstHashFileReturnsFailure)
267{
268 openToInProgress(hashBlobId);
269 EXPECT_FALSE(handler->commit(session, {}));
270}
Patrick Venture41205cc2019-05-23 11:43:43 -0700271
Patrick Ventureebcc5222019-05-23 10:36:40 -0700272} // namespace
273} // namespace ipmi_flash