1 /* The goal of these tests is to verify the behavior of all blob commands given 2 * the current state is verificationStarted. This state is achieved as a out of 3 * verificationPending. 4 */ 5 #include "firmware_handler.hpp" 6 #include "firmware_unittest.hpp" 7 #include "status.hpp" 8 #include "util.hpp" 9 10 #include <cstdint> 11 #include <string> 12 #include <vector> 13 14 #include <gtest/gtest.h> 15 16 namespace ipmi_flash 17 { 18 namespace 19 { 20 21 using ::testing::IsEmpty; 22 using ::testing::Return; 23 using ::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) 37 * commit(session) 38 * 39 * Testing canHandleBlob is uninteresting in this state. Getting the BlobIDs 40 * will inform what canHandleBlob will return. 41 */ 42 43 class FirmwareHandlerVerificationStartedTest : public IpmiOnlyFirmwareStaticTest 44 {}; 45 46 /* 47 * canHandleBlob(blob) 48 * getBlobIds() 49 */ 50 TEST_F(FirmwareHandlerVerificationStartedTest, GetBlobIdsReturnsExpectedList) 51 { 52 getToVerificationStarted(staticLayoutBlobId); 53 54 auto blobs = handler->getBlobIds(); 55 EXPECT_THAT( 56 blobs, UnorderedElementsAreArray({activeImageBlobId, staticLayoutBlobId, 57 hashBlobId, verifyBlobId})); 58 59 for (const auto& blob : blobs) 60 { 61 EXPECT_TRUE(handler->canHandleBlob(blob)); 62 } 63 } 64 65 /* 66 * stat(session) 67 */ 68 TEST_F(FirmwareHandlerVerificationStartedTest, 69 StatOnVerifyBlobIdAfterCommitChecksStateAndReturnsRunning) 70 { 71 getToVerificationStarted(staticLayoutBlobId); 72 EXPECT_CALL(*verifyMockPtr, status()) 73 .WillOnce(Return(ActionStatus::running)); 74 75 blobs::BlobMeta meta, expectedMeta = {}; 76 expectedMeta.size = 0; 77 expectedMeta.blobState = flags | blobs::StateFlags::committing; 78 expectedMeta.metadata.push_back( 79 static_cast<std::uint8_t>(ActionStatus::running)); 80 81 EXPECT_TRUE(handler->stat(session, &meta)); 82 EXPECT_EQ(expectedMeta, meta); 83 } 84 85 TEST_F(FirmwareHandlerVerificationStartedTest, 86 StatOnVerifyBlobIdAfterCommitChecksStateAndReturnsOther) 87 { 88 getToVerificationStarted(staticLayoutBlobId); 89 EXPECT_CALL(*verifyMockPtr, status()) 90 .WillOnce(Return(ActionStatus::unknown)); 91 92 blobs::BlobMeta meta, expectedMeta = {}; 93 expectedMeta.size = 0; 94 expectedMeta.blobState = flags | blobs::StateFlags::committing; 95 expectedMeta.metadata.push_back( 96 static_cast<std::uint8_t>(ActionStatus::unknown)); 97 98 EXPECT_TRUE(handler->stat(session, &meta)); 99 EXPECT_EQ(expectedMeta, meta); 100 } 101 102 TEST_F(FirmwareHandlerVerificationStartedTest, 103 StatOnVerifyBlobIdAfterCommitCheckStateAndReturnsFailed) 104 { 105 /* If the returned state from the verification handler is failed, it sets 106 * commit_error and transitions to verificationCompleted. 107 */ 108 getToVerificationStarted(staticLayoutBlobId); 109 EXPECT_CALL(*verifyMockPtr, status()) 110 .WillOnce(Return(ActionStatus::failed)); 111 112 blobs::BlobMeta meta, expectedMeta = {}; 113 expectedMeta.size = 0; 114 expectedMeta.blobState = flags | blobs::StateFlags::commit_error; 115 expectedMeta.metadata.push_back( 116 static_cast<std::uint8_t>(ActionStatus::failed)); 117 118 EXPECT_TRUE(handler->stat(session, &meta)); 119 EXPECT_EQ(expectedMeta, meta); 120 expectedState(FirmwareBlobHandler::UpdateState::verificationCompleted); 121 } 122 123 TEST_F(FirmwareHandlerVerificationStartedTest, 124 StatOnVerifyBlobIdAfterCommitCheckStateAndReturnsSuccess) 125 { 126 /* If the returned state from the verification handler is success, it sets 127 * committed and transitions to verificationCompleted. 128 */ 129 getToVerificationStarted(staticLayoutBlobId); 130 EXPECT_CALL(*verifyMockPtr, status()) 131 .WillOnce(Return(ActionStatus::success)); 132 133 blobs::BlobMeta meta, expectedMeta = {}; 134 expectedMeta.size = 0; 135 expectedMeta.blobState = flags | blobs::StateFlags::committed; 136 expectedMeta.metadata.push_back( 137 static_cast<std::uint8_t>(ActionStatus::success)); 138 139 EXPECT_TRUE(handler->stat(session, &meta)); 140 EXPECT_EQ(expectedMeta, meta); 141 expectedState(FirmwareBlobHandler::UpdateState::verificationCompleted); 142 } 143 144 /* 145 * deleteBlob(blob) 146 */ 147 TEST_F(FirmwareHandlerVerificationStartedTest, DeleteBlobReturnsFalse) 148 { 149 /* Try deleting all blobs, it doesn't really matter which though because you 150 * cannot close out an open session, therefore you must fail to delete 151 * anything unless everything is closed. 152 */ 153 getToVerificationStarted(staticLayoutBlobId); 154 auto blobs = handler->getBlobIds(); 155 for (const auto& b : blobs) 156 { 157 EXPECT_FALSE(handler->deleteBlob(b)); 158 } 159 } 160 161 /* 162 * stat(blob) 163 */ 164 TEST_F(FirmwareHandlerVerificationStartedTest, StatOnActiveImageReturnsFailure) 165 { 166 getToVerificationStarted(staticLayoutBlobId); 167 ASSERT_TRUE(handler->canHandleBlob(activeImageBlobId)); 168 169 blobs::BlobMeta meta; 170 EXPECT_FALSE(handler->stat(activeImageBlobId, &meta)); 171 } 172 173 TEST_F(FirmwareHandlerVerificationStartedTest, StatOnActiveHashReturnsFailure) 174 { 175 getToVerificationStartedWitHashBlob(); 176 ASSERT_TRUE(handler->canHandleBlob(activeHashBlobId)); 177 178 blobs::BlobMeta meta; 179 EXPECT_FALSE(handler->stat(activeHashBlobId, &meta)); 180 } 181 182 TEST_F(FirmwareHandlerVerificationStartedTest, StatOnVerifyBlobReturnsFailure) 183 { 184 /* the verifyBlobId is available starting at verificationPending. */ 185 getToVerificationStarted(staticLayoutBlobId); 186 ASSERT_TRUE(handler->canHandleBlob(verifyBlobId)); 187 188 blobs::BlobMeta meta; 189 EXPECT_FALSE(handler->stat(verifyBlobId, &meta)); 190 } 191 192 TEST_F(FirmwareHandlerVerificationStartedTest, StatOnNormalBlobsReturnsSuccess) 193 { 194 getToVerificationStarted(staticLayoutBlobId); 195 196 std::vector<std::string> testBlobs = {staticLayoutBlobId, hashBlobId}; 197 for (const auto& blob : testBlobs) 198 { 199 ASSERT_TRUE(handler->canHandleBlob(blob)); 200 201 blobs::BlobMeta meta = {}; 202 EXPECT_TRUE(handler->stat(blob, &meta)); 203 EXPECT_EQ(expectedIdleMeta, meta); 204 } 205 } 206 207 /* 208 * writemeta(session) 209 */ 210 TEST_F(FirmwareHandlerVerificationStartedTest, 211 WriteMetaOnVerifySessionReturnsFailure) 212 { 213 getToVerificationStarted(staticLayoutBlobId); 214 215 std::vector<std::uint8_t> bytes = {0x01, 0x02}; 216 EXPECT_FALSE(handler->writeMeta(session, 0, bytes)); 217 } 218 219 /* 220 * write(session) 221 */ 222 TEST_F(FirmwareHandlerVerificationStartedTest, 223 WriteOnVerifySessionReturnsFailure) 224 { 225 getToVerificationStarted(staticLayoutBlobId); 226 227 std::vector<std::uint8_t> bytes = {0x01, 0x02}; 228 EXPECT_FALSE(handler->write(session, 0, bytes)); 229 } 230 231 /* 232 * open(blob) - there is nothing you can open, this state has an open file. 233 */ 234 TEST_F(FirmwareHandlerVerificationStartedTest, 235 AttemptToOpenImageFileReturnsFailure) 236 { 237 /* Attempt to open a file one normally can open, however, as there is 238 * already a file open, this will fail. 239 */ 240 getToVerificationStarted(staticLayoutBlobId); 241 242 auto blobsToOpen = handler->getBlobIds(); 243 for (const auto& blob : blobsToOpen) 244 { 245 EXPECT_FALSE(handler->open(session + 1, flags, blob)); 246 } 247 } 248 249 /* 250 * read(session) 251 */ 252 TEST_F(FirmwareHandlerVerificationStartedTest, ReadOfVerifyBlobReturnsEmpty) 253 { 254 getToVerificationStarted(staticLayoutBlobId); 255 EXPECT_THAT(handler->read(session, 0, 1), IsEmpty()); 256 } 257 258 /* 259 * commit(session) 260 */ 261 TEST_F(FirmwareHandlerVerificationStartedTest, 262 CommitOnVerifyDuringVerificationHasNoImpact) 263 { 264 getToVerificationStarted(staticLayoutBlobId); 265 EXPECT_TRUE(handler->commit(session, {})); 266 expectedState(FirmwareBlobHandler::UpdateState::verificationStarted); 267 } 268 269 /* 270 * close(session) - close while state if verificationStarted without calling 271 * stat first will abort. 272 */ 273 TEST_F(FirmwareHandlerVerificationStartedTest, 274 CloseOnVerifyDuringVerificationAbortsProcess) 275 { 276 getToVerificationStarted(staticLayoutBlobId); 277 EXPECT_CALL(*verifyMockPtr, abort()).Times(1); 278 279 EXPECT_TRUE(handler->close(session)); 280 281 EXPECT_THAT(handler->getBlobIds(), 282 UnorderedElementsAreArray(startingBlobs)); 283 284 expectedState(FirmwareBlobHandler::UpdateState::notYetStarted); 285 } 286 287 /* 288 * expire(session) 289 */ 290 TEST_F(FirmwareHandlerVerificationStartedTest, 291 ExpireOnSessionDuringVerificationAbortsProcess) 292 { 293 getToVerificationStarted(staticLayoutBlobId); 294 EXPECT_CALL(*verifyMockPtr, abort()).Times(0); 295 296 EXPECT_TRUE(handler->expire(session)); 297 298 EXPECT_THAT(handler->getBlobIds(), 299 UnorderedElementsAreArray(startingBlobs)); 300 301 expectedState(FirmwareBlobHandler::UpdateState::notYetStarted); 302 } 303 304 } // namespace 305 } // namespace ipmi_flash 306