blob: 6c3b607331e0c76fdc9eaae0a343d150354acaed [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 Venture41205cc2019-05-23 11:43:43 -070068/*
69 * stat(blob)
70 */
71TEST_F(FirmwareHandlerUploadInProgressTest, StatOnActiveImageReturnsFailure)
72{
73 /* you cannot call stat() on the active image or the active hash or the
74 * verify blob.
75 */
Patrick Venturebe0fb5e2019-05-23 16:14:20 -070076 openToInProgress(staticLayoutBlobId);
Patrick Venture930c7b72019-05-24 11:11:08 -070077 ASSERT_TRUE(handler->canHandleBlob(activeImageBlobId));
Patrick Venture41205cc2019-05-23 11:43:43 -070078
Patrick Venture41205cc2019-05-23 11:43:43 -070079 blobs::BlobMeta meta;
80 EXPECT_FALSE(handler->stat(activeImageBlobId, &meta));
81}
82
83TEST_F(FirmwareHandlerUploadInProgressTest, StatOnActiveHashReturnsFailure)
84{
85 /* this test is separate from the active image one so that the state doesn't
86 * change from close.
87 */
Patrick Venturebe0fb5e2019-05-23 16:14:20 -070088 openToInProgress(hashBlobId);
Patrick Venture930c7b72019-05-24 11:11:08 -070089 ASSERT_TRUE(handler->canHandleBlob(activeHashBlobId));
Patrick Venture41205cc2019-05-23 11:43:43 -070090
Patrick Venture41205cc2019-05-23 11:43:43 -070091 blobs::BlobMeta meta;
92 EXPECT_FALSE(handler->stat(activeHashBlobId, &meta));
93}
94
95TEST_F(FirmwareHandlerUploadInProgressTest, StatOnNormalBlobsReturnsSuccess)
96{
97 /* Calling stat() on the normal blobs (not the active) ones will work and
98 * return the same information as in the notYetStarted state.
99 */
100 blobs::BlobMeta expected;
101 expected.blobState = FirmwareBlobHandler::UpdateFlags::ipmi;
102 expected.size = 0;
103
Patrick Venturebe0fb5e2019-05-23 16:14:20 -0700104 openToInProgress(staticLayoutBlobId);
Patrick Venture41205cc2019-05-23 11:43:43 -0700105
106 std::vector<std::string> testBlobs = {staticLayoutBlobId, hashBlobId};
107 for (const auto& blob : testBlobs)
108 {
109 blobs::BlobMeta meta = {};
110 EXPECT_TRUE(handler->stat(blob, &meta));
111 EXPECT_EQ(expected, meta);
112 }
113}
114
Patrick Venture41205cc2019-05-23 11:43:43 -0700115/*
116 * stat(session)
Patrick Ventureefc366e2019-05-23 12:00:21 -0700117 */
118TEST_F(FirmwareHandlerUploadInProgressTest,
119 CallingStatOnActiveImageOrHashSessionReturnsDetails)
120{
121 /* This test will verify that the underlying image handler is called with
122 * this stat, in addition to the normal information.
123 */
Patrick Venturebe0fb5e2019-05-23 16:14:20 -0700124 openToInProgress(staticLayoutBlobId);
Patrick Ventureefc366e2019-05-23 12:00:21 -0700125
126 EXPECT_CALL(imageMock, getSize()).WillOnce(Return(32));
127
128 blobs::BlobMeta meta, expectedMeta = {};
129 expectedMeta.size = 32;
130 expectedMeta.blobState =
131 blobs::OpenFlags::write | FirmwareBlobHandler::UpdateFlags::ipmi;
132 EXPECT_TRUE(handler->stat(session, &meta));
133 EXPECT_EQ(expectedMeta, meta);
134}
135
136/*
Patrick Venture5788dbb2019-05-23 12:25:42 -0700137 * open(blob) - While any blob is open, all other fail.
Patrick Venture072a7dd2019-05-28 13:51:26 -0700138 *
139 * The fullBlobsList is all the blob_ids present if both /flash/image and
140 * /flash/hash are opened, and one is left open (so there's no verify blob). if
141 * left closed, we'd be in verificationPending, not uploadInProgress.
Patrick Venture5788dbb2019-05-23 12:25:42 -0700142 */
Patrick Venture072a7dd2019-05-28 13:51:26 -0700143const std::vector<std::string> fullBlobsList = {
144 activeHashBlobId, activeImageBlobId, hashBlobId, staticLayoutBlobId};
145
Patrick Venture5788dbb2019-05-23 12:25:42 -0700146TEST_F(FirmwareHandlerUploadInProgressTest, OpeningHashFileWhileImageOpenFails)
147{
148 /* To be in this state, something must be open (and specifically either an
149 * active image (or tarball) or the hash file. Also verifies you can't just
150 * re-open the currently open file.
151 */
Patrick Venturebe0fb5e2019-05-23 16:14:20 -0700152 openToInProgress(staticLayoutBlobId);
Patrick Venture5788dbb2019-05-23 12:25:42 -0700153
Patrick Venture072a7dd2019-05-28 13:51:26 -0700154 for (const auto& blob : fullBlobsList)
Patrick Venture5788dbb2019-05-23 12:25:42 -0700155 {
156 EXPECT_FALSE(handler->open(2, flags, blob));
157 }
158}
159
160TEST_F(FirmwareHandlerUploadInProgressTest, OpeningImageFileWhileHashOpenFails)
161{
Patrick Venturebe0fb5e2019-05-23 16:14:20 -0700162 openToInProgress(hashBlobId);
Patrick Venture5788dbb2019-05-23 12:25:42 -0700163
Patrick Venture072a7dd2019-05-28 13:51:26 -0700164 for (const auto& blob : fullBlobsList)
Patrick Venture5788dbb2019-05-23 12:25:42 -0700165 {
166 EXPECT_FALSE(handler->open(2, flags, blob));
167 }
168}
169
170/*
Patrick Venture79b44742019-05-23 12:36:11 -0700171 * close(session) - closing the hash or image will trigger a state transition to
172 * verificationPending.
Patrick Venture79b44742019-05-23 12:36:11 -0700173 *
174 * NOTE: Re-opening /flash/image will transition back to uploadInProgress, but
175 * that is verified in the verificationPending::open tests.
176 */
177TEST_F(FirmwareHandlerUploadInProgressTest,
178 ClosingImageFileTransitionsToVerificationPending)
179{
Patrick Venture930c7b72019-05-24 11:11:08 -0700180 EXPECT_FALSE(handler->canHandleBlob(verifyBlobId));
Patrick Venture6fdd02e2019-05-28 13:02:04 -0700181 openToInProgress(staticLayoutBlobId);
Patrick Venture79b44742019-05-23 12:36:11 -0700182
Patrick Venture6fdd02e2019-05-28 13:02:04 -0700183 handler->close(session);
184 expectedState(FirmwareBlobHandler::UpdateState::verificationPending);
Patrick Venture79b44742019-05-23 12:36:11 -0700185
186 EXPECT_TRUE(handler->canHandleBlob(verifyBlobId));
187}
188
189TEST_F(FirmwareHandlerUploadInProgressTest,
190 ClosingHashFileTransitionsToVerificationPending)
191{
Patrick Venture930c7b72019-05-24 11:11:08 -0700192 EXPECT_FALSE(handler->canHandleBlob(verifyBlobId));
Patrick Venture6fdd02e2019-05-28 13:02:04 -0700193 openToInProgress(hashBlobId);
Patrick Venture79b44742019-05-23 12:36:11 -0700194
Patrick Venture6fdd02e2019-05-28 13:02:04 -0700195 handler->close(session);
196 expectedState(FirmwareBlobHandler::UpdateState::verificationPending);
Patrick Venture79b44742019-05-23 12:36:11 -0700197
198 EXPECT_TRUE(handler->canHandleBlob(verifyBlobId));
199}
200
201/*
Patrick Venture41205cc2019-05-23 11:43:43 -0700202 * writemeta(session)
Patrick Venture7cf44402019-05-23 13:01:47 -0700203 */
Patrick Venture31eefd42019-05-23 20:27:41 -0700204TEST_F(FirmwareHandlerUploadInProgressTest,
205 WriteMetaAgainstImageReturnsFailureIfNoDataHandler)
Patrick Venture7cf44402019-05-23 13:01:47 -0700206{
207 /* Calling write/read/writeMeta are uninteresting against the open blob in
208 * this case because the blob will just pass the call along. Whereas
209 * calling against the verify or update blob may be more interesting.
210 */
Patrick Venturebe0fb5e2019-05-23 16:14:20 -0700211 openToInProgress(staticLayoutBlobId);
Patrick Venture7cf44402019-05-23 13:01:47 -0700212
Patrick Venture31eefd42019-05-23 20:27:41 -0700213 /* TODO: Consider adding a test that has a data handler, but that test
214 * already exists under the general writeMeta test suite.
215 */
Patrick Venture7cf44402019-05-23 13:01:47 -0700216 /* Note: with IPMI as the transport there's no data handler, so this should
217 * fail nicely. */
218 std::vector<std::uint8_t> bytes = {0x01, 0x02};
Patrick Venturebe0fb5e2019-05-23 16:14:20 -0700219 EXPECT_FALSE(handler->writeMeta(session, 0, bytes));
Patrick Venture7cf44402019-05-23 13:01:47 -0700220}
221
222/*
Patrick Venture41205cc2019-05-23 11:43:43 -0700223 * write(session)
Patrick Venture615123a2019-05-23 17:20:07 -0700224 */
225TEST_F(FirmwareHandlerUploadInProgressTest, WriteToImageReturnsSuccess)
226{
227 openToInProgress(staticLayoutBlobId);
228 std::vector<std::uint8_t> bytes = {0x01, 0x02};
229 EXPECT_CALL(imageMock, write(0, ContainerEq(bytes))).WillOnce(Return(true));
230 EXPECT_TRUE(handler->write(session, 0, bytes));
231}
232
233TEST_F(FirmwareHandlerUploadInProgressTest, WriteToHashReturnsSuccess)
234{
235 openToInProgress(hashBlobId);
236 std::vector<std::uint8_t> bytes = {0x01, 0x02};
237 EXPECT_CALL(imageMock, write(0, ContainerEq(bytes))).WillOnce(Return(true));
238 EXPECT_TRUE(handler->write(session, 0, bytes));
239}
240
241/*
Patrick Venture41205cc2019-05-23 11:43:43 -0700242 * read(session)
Patrick Venture615123a2019-05-23 17:20:07 -0700243 */
Patrick Venture8326d072019-05-23 17:45:42 -0700244TEST_F(FirmwareHandlerUploadInProgressTest, ReadImageFileReturnsFailure)
245{
246 /* Read is not supported. */
247 openToInProgress(staticLayoutBlobId);
248 EXPECT_THAT(handler->read(session, 0, 32), IsEmpty());
249}
Patrick Venture615123a2019-05-23 17:20:07 -0700250
251/*
Patrick Venturebe0fb5e2019-05-23 16:14:20 -0700252 * commit(session)
Patrick Venture41205cc2019-05-23 11:43:43 -0700253 */
Patrick Venture1fca1902019-05-23 17:54:18 -0700254TEST_F(FirmwareHandlerUploadInProgressTest,
255 CommitAgainstImageFileReturnsFailure)
256{
257 /* Commit is only valid against specific blobs. */
258 openToInProgress(staticLayoutBlobId);
259 EXPECT_FALSE(handler->commit(session, {}));
260}
261
262TEST_F(FirmwareHandlerUploadInProgressTest, CommitAgainstHashFileReturnsFailure)
263{
264 openToInProgress(hashBlobId);
265 EXPECT_FALSE(handler->commit(session, {}));
266}
Patrick Venture41205cc2019-05-23 11:43:43 -0700267
Patrick Venturebcc0c772019-06-17 10:42:06 -0700268/*
269 * deleteBlob(blob)
270 */
271TEST_F(FirmwareHandlerUploadInProgressTest, DeleteBlobReturnsFalse)
272{
273 /* Try deleting all blobs, it doesn't really matter which though because you
274 * cannot close out an open session, therefore you must fail to delete
275 * anything unless everything is closed.
276 */
277 openToInProgress(staticLayoutBlobId);
278 auto blobs = handler->getBlobIds();
279 for (const auto& b : blobs)
280 {
281 EXPECT_FALSE(handler->deleteBlob(b));
282 }
283}
284
Patrick Ventureebcc5222019-05-23 10:36:40 -0700285} // namespace
286} // namespace ipmi_flash