blob: af777c75f44ffda1e1e60160c8e27c18797a1d9c [file] [log] [blame]
Patrick Venture61d2ed42019-05-23 18:16:31 -07001/**
2 * The goal of these tests is to verify the behavior of all blob commands given
3 * the current state is verificationPending. This state is achieved as a
4 * transition out of uploadInProgress.
5 */
6#include "firmware_handler.hpp"
7#include "firmware_unittest.hpp"
Patrick Venture01a33272019-05-23 19:48:22 -07008#include "status.hpp"
Patrick Venture61d2ed42019-05-23 18:16:31 -07009#include "util.hpp"
10
11#include <cstdint>
12#include <string>
13#include <vector>
14
15#include <gtest/gtest.h>
16
17namespace ipmi_flash
18{
19namespace
20{
21
Patrick Venture2567ebc2019-05-24 10:02:53 -070022using ::testing::IsEmpty;
Patrick Venture61d2ed42019-05-23 18:16:31 -070023using ::testing::Return;
Patrick Ventureefba42d2019-05-24 10:48:16 -070024using ::testing::UnorderedElementsAreArray;
Patrick Venture61d2ed42019-05-23 18:16:31 -070025
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)
38 * commit(session)
39 *
40 * Testing canHandleBlob is uninteresting in this state. Getting the BlobIDs
41 * will inform what canHandleBlob will return.
42 */
43
44class FirmwareHandlerVerificationPendingTest : public IpmiOnlyFirmwareStaticTest
45{
46 protected:
47 void getToVerificationPending(const std::string& blobId)
48 {
49 auto realHandler = dynamic_cast<FirmwareBlobHandler*>(handler.get());
50 EXPECT_CALL(imageMock, open(blobId)).WillOnce(Return(true));
51 EXPECT_TRUE(handler->open(session, flags, blobId));
52 EXPECT_EQ(FirmwareBlobHandler::UpdateState::uploadInProgress,
53 realHandler->getCurrentState());
54 EXPECT_CALL(imageMock, close()).WillRepeatedly(Return());
55 handler->close(session);
56 EXPECT_EQ(FirmwareBlobHandler::UpdateState::verificationPending,
57 realHandler->getCurrentState());
58 }
59
60 std::uint16_t session = 1;
61 std::uint16_t flags =
62 blobs::OpenFlags::write | FirmwareBlobHandler::UpdateFlags::ipmi;
63};
64
65/*
66 * getBlobIds
Patrick Venture61d2ed42019-05-23 18:16:31 -070067 */
Patrick Venture61d2ed42019-05-23 18:16:31 -070068TEST_F(FirmwareHandlerVerificationPendingTest, VerifyBlobIdAvailableInState)
69{
70 /* Only in the verificationPending state (and later), should the
71 * verifyBlobId be present. */
72
73 /* TODO: Add this test in when the change is made. */
74 // EXPECT_FALSE(handler->canHandleBlob(verifyBlobId));
75 getToVerificationPending(staticLayoutBlobId);
76 EXPECT_TRUE(handler->canHandleBlob(verifyBlobId));
Patrick Ventureb386b862019-05-23 18:42:54 -070077 EXPECT_TRUE(handler->canHandleBlob(activeImageBlobId));
Patrick Venture61d2ed42019-05-23 18:16:31 -070078}
79
Patrick Ventureb386b862019-05-23 18:42:54 -070080/*
81 * delete(blob) TODO: Implement this.
82 */
83
84/*
85 * stat(blob)
86 */
87TEST_F(FirmwareHandlerVerificationPendingTest, StatOnActiveImageReturnsFailure)
88{
89 getToVerificationPending(staticLayoutBlobId);
90
91 blobs::BlobMeta meta;
92 EXPECT_FALSE(handler->stat(activeImageBlobId, &meta));
93}
94
95TEST_F(FirmwareHandlerVerificationPendingTest, StatOnActiveHashReturnsFailure)
96{
97 getToVerificationPending(hashBlobId);
98
99 blobs::BlobMeta meta;
100 EXPECT_FALSE(handler->stat(activeHashBlobId, &meta));
101}
102
103TEST_F(FirmwareHandlerVerificationPendingTest,
104 StatOnVerificationBlobReturnsFailure)
105{
106 getToVerificationPending(hashBlobId);
107
108 blobs::BlobMeta meta;
109 EXPECT_FALSE(handler->stat(verifyBlobId, &meta));
110}
111
112TEST_F(FirmwareHandlerVerificationPendingTest, StatOnNormalBlobsReturnsSuccess)
113{
114 getToVerificationPending(staticLayoutBlobId);
115
116 blobs::BlobMeta expected;
117 expected.blobState = FirmwareBlobHandler::UpdateFlags::ipmi;
118 expected.size = 0;
119
120 std::vector<std::string> testBlobs = {staticLayoutBlobId, hashBlobId};
121 for (const auto& blob : testBlobs)
122 {
123 blobs::BlobMeta meta = {};
124 EXPECT_TRUE(handler->stat(blob, &meta));
125 EXPECT_EQ(expected, meta);
126 }
127}
128
129/*
Patrick Ventureb386b862019-05-23 18:42:54 -0700130 * open(blob)
131 */
Patrick Ventureda8fcd12019-05-23 18:53:50 -0700132TEST_F(FirmwareHandlerVerificationPendingTest, OpenVerifyBlobSucceeds)
133{
134 getToVerificationPending(staticLayoutBlobId);
135
136 /* the session is safe because it was already closed to get to this state.
137 */
138 EXPECT_TRUE(handler->open(session, flags, verifyBlobId));
139}
140
141TEST_F(FirmwareHandlerVerificationPendingTest, OpenActiveImageBlobFails)
142{
143 /* Try opening the active blob Id. This test is equivalent to trying to
144 * open the active hash blob id, in that neither are ever allowed.
145 */
146 getToVerificationPending(staticLayoutBlobId);
147 EXPECT_FALSE(handler->open(session, flags, activeImageBlobId));
148}
149
150TEST_F(FirmwareHandlerVerificationPendingTest,
151 OpenImageBlobTransitionsToUploadInProgress)
152{
153 getToVerificationPending(staticLayoutBlobId);
Patrick Ventureefba42d2019-05-24 10:48:16 -0700154
155 /* Verify the active blob for the image is in the list once to start.
156 * Note: This is truly tested under the notYetStarted::open() test.
157 */
158 std::vector<std::string> expectedBlobs = {staticLayoutBlobId, hashBlobId,
159 verifyBlobId, activeImageBlobId};
160
161 EXPECT_THAT(handler->getBlobIds(),
162 UnorderedElementsAreArray(expectedBlobs));
163
Patrick Ventureda8fcd12019-05-23 18:53:50 -0700164 EXPECT_CALL(imageMock, open(staticLayoutBlobId)).WillOnce(Return(true));
165 EXPECT_TRUE(handler->open(session, flags, staticLayoutBlobId));
166
167 auto realHandler = dynamic_cast<FirmwareBlobHandler*>(handler.get());
168 EXPECT_EQ(FirmwareBlobHandler::UpdateState::uploadInProgress,
169 realHandler->getCurrentState());
Patrick Ventureefba42d2019-05-24 10:48:16 -0700170
171 /* Verify the active blob ID was not added to the list twice. */
172 EXPECT_THAT(handler->getBlobIds(),
173 UnorderedElementsAreArray(expectedBlobs));
Patrick Ventureda8fcd12019-05-23 18:53:50 -0700174}
175
176/*
Patrick Venture1e389c92019-05-23 19:15:05 -0700177 * close(session)
178 */
179TEST_F(FirmwareHandlerVerificationPendingTest,
180 ClosingVerifyBlobDoesNotChangeState)
181{
182 getToVerificationPending(staticLayoutBlobId);
183 EXPECT_TRUE(handler->open(session, flags, verifyBlobId));
184
185 auto realHandler = dynamic_cast<FirmwareBlobHandler*>(handler.get());
186 EXPECT_EQ(FirmwareBlobHandler::UpdateState::verificationPending,
187 realHandler->getCurrentState());
188
189 handler->close(session);
190
191 EXPECT_EQ(FirmwareBlobHandler::UpdateState::verificationPending,
192 realHandler->getCurrentState());
193}
194
195/*
Patrick Venture19044e12019-05-23 19:30:28 -0700196 * commit(session)
197 */
198TEST_F(FirmwareHandlerVerificationPendingTest,
199 CommitOnVerifyBlobTriggersVerificationAndStateTransition)
200{
201 getToVerificationPending(staticLayoutBlobId);
202 EXPECT_TRUE(handler->open(session, flags, verifyBlobId));
203 EXPECT_CALL(*verifyMockPtr, triggerVerification()).WillOnce(Return(true));
204
205 EXPECT_TRUE(handler->commit(session, {}));
206
207 auto realHandler = dynamic_cast<FirmwareBlobHandler*>(handler.get());
208 EXPECT_EQ(FirmwareBlobHandler::UpdateState::verificationStarted,
209 realHandler->getCurrentState());
210}
211
212/*
Patrick Ventureda8fcd12019-05-23 18:53:50 -0700213 * stat(session) - in this state, you can only open(verifyBlobId) without
214 * changing state.
215 */
Patrick Venture01a33272019-05-23 19:48:22 -0700216TEST_F(FirmwareHandlerVerificationPendingTest, StatOnVerifyBlobIdReturnsState)
217{
218 /* If this is called before commit(), it's still verificationPending, so it
219 * just returns the state is other
220 */
221 getToVerificationPending(staticLayoutBlobId);
222 EXPECT_TRUE(handler->open(session, flags, verifyBlobId));
223 EXPECT_CALL(*verifyMockPtr, triggerVerification()).Times(0);
224 EXPECT_CALL(*verifyMockPtr, checkVerificationState()).Times(0);
225
226 blobs::BlobMeta meta, expectedMeta = {};
227 expectedMeta.size = 0;
228 expectedMeta.blobState = flags;
229 expectedMeta.metadata.push_back(
230 static_cast<std::uint8_t>(VerifyCheckResponses::other));
231
232 EXPECT_TRUE(handler->stat(session, &meta));
233 EXPECT_EQ(expectedMeta, meta);
234}
235
Patrick Ventureb386b862019-05-23 18:42:54 -0700236/*
Patrick Ventureb386b862019-05-23 18:42:54 -0700237 * writemeta(session)
238 */
Patrick Ventureb611a082019-05-23 20:27:28 -0700239TEST_F(FirmwareHandlerVerificationPendingTest, WriteMetaAgainstVerifyFails)
240{
241 /* The verifyBlobId has no data handler, which means write meta fails. */
242 getToVerificationPending(staticLayoutBlobId);
243
244 EXPECT_TRUE(handler->open(session, flags, verifyBlobId));
245
246 std::vector<std::uint8_t> bytes = {0x01, 0x02};
247 EXPECT_FALSE(handler->writeMeta(session, 0, bytes));
248}
249
Patrick Ventureb386b862019-05-23 18:42:54 -0700250/*
251 * write(session)
252 */
Patrick Ventureab731e92019-05-24 09:58:00 -0700253TEST_F(FirmwareHandlerVerificationPendingTest, WriteAgainstVerifyBlobIdFails)
254{
255 getToVerificationPending(staticLayoutBlobId);
256
257 EXPECT_TRUE(handler->open(session, flags, verifyBlobId));
258
259 std::vector<std::uint8_t> bytes = {0x01, 0x02};
260 EXPECT_FALSE(handler->write(session, 0, bytes));
261}
262
Patrick Ventureb386b862019-05-23 18:42:54 -0700263/*
264 * read(session)
265 */
Patrick Venture2567ebc2019-05-24 10:02:53 -0700266TEST_F(FirmwareHandlerVerificationPendingTest,
267 ReadAgainstVerifyBlobIdReturnsEmpty)
268{
269 getToVerificationPending(staticLayoutBlobId);
270
271 EXPECT_TRUE(handler->open(session, flags, verifyBlobId));
272 EXPECT_THAT(handler->read(session, 0, 32), IsEmpty());
273}
Patrick Ventureb386b862019-05-23 18:42:54 -0700274
Patrick Venture61d2ed42019-05-23 18:16:31 -0700275} // namespace
276} // namespace ipmi_flash