1 /* The goal of these tests is to verify the behavior of all blob commands given 2 * the current state is UpdateCompleted. This state is achieved as an exit from 3 * updateStarted. 4 * 5 * This can be reached with success or failure from an update, and is reached 6 * via a stat() call from updatedStarted. 7 */ 8 #include "firmware_handler.hpp" 9 #include "firmware_unittest.hpp" 10 #include "status.hpp" 11 #include "util.hpp" 12 13 #include <string> 14 #include <vector> 15 16 #include <gtest/gtest.h> 17 18 namespace ipmi_flash 19 { 20 namespace 21 { 22 23 using ::testing::IsEmpty; 24 using ::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) 38 * commit(session) 39 */ 40 41 class FirmwareHandlerUpdateCompletedTest : public IpmiOnlyFirmwareStaticTest 42 {}; 43 44 /* 45 * open(blob) 46 */ 47 TEST_F(FirmwareHandlerUpdateCompletedTest, 48 AttemptToOpenFilesReturnsFailureAfterSuccess) 49 { 50 /* In state updateCompleted a file is open, which means no others can be. */ 51 getToUpdateCompleted(ActionStatus::success); 52 53 auto blobsToOpen = handler->getBlobIds(); 54 for (const auto& blob : blobsToOpen) 55 { 56 EXPECT_FALSE(handler->open(session + 1, flags, blob)); 57 } 58 } 59 60 /* 61 * stat(session) 62 */ 63 TEST_F(FirmwareHandlerUpdateCompletedTest, 64 CallingStatSessionAfterCompletedSuccessReturnsStateWithoutRechecking) 65 { 66 getToUpdateCompleted(ActionStatus::success); 67 EXPECT_CALL(*updateMockPtr, status()).Times(0); 68 69 blobs::BlobMeta meta, expectedMeta = {}; 70 expectedMeta.size = 0; 71 expectedMeta.blobState = flags | blobs::StateFlags::committed; 72 expectedMeta.metadata.push_back( 73 static_cast<std::uint8_t>(ActionStatus::success)); 74 75 EXPECT_TRUE(handler->stat(session, &meta)); 76 EXPECT_EQ(expectedMeta, meta); 77 expectedState(FirmwareBlobHandler::UpdateState::updateCompleted); 78 } 79 80 TEST_F(FirmwareHandlerUpdateCompletedTest, 81 CallingStatSessionAfterCompletedFailureReturnsStateWithoutRechecking) 82 { 83 getToUpdateCompleted(ActionStatus::failed); 84 EXPECT_CALL(*updateMockPtr, status()).Times(0); 85 86 blobs::BlobMeta meta, expectedMeta = {}; 87 expectedMeta.size = 0; 88 expectedMeta.blobState = flags | blobs::StateFlags::commit_error; 89 expectedMeta.metadata.push_back( 90 static_cast<std::uint8_t>(ActionStatus::failed)); 91 92 EXPECT_TRUE(handler->stat(session, &meta)); 93 EXPECT_EQ(expectedMeta, meta); 94 expectedState(FirmwareBlobHandler::UpdateState::updateCompleted); 95 } 96 97 /* 98 * stat(blob) 99 */ 100 TEST_F(FirmwareHandlerUpdateCompletedTest, StatOnActiveImageReturnsFailure) 101 { 102 getToUpdateCompleted(ActionStatus::success); 103 104 ASSERT_TRUE(handler->canHandleBlob(activeImageBlobId)); 105 106 blobs::BlobMeta meta; 107 EXPECT_FALSE(handler->stat(activeImageBlobId, &meta)); 108 } 109 110 TEST_F(FirmwareHandlerUpdateCompletedTest, StatOnUpdateBlobReturnsFailure) 111 { 112 getToUpdateCompleted(ActionStatus::success); 113 114 ASSERT_TRUE(handler->canHandleBlob(updateBlobId)); 115 116 blobs::BlobMeta meta; 117 EXPECT_FALSE(handler->stat(updateBlobId, &meta)); 118 } 119 120 TEST_F(FirmwareHandlerUpdateCompletedTest, StatOnNormalBlobsReturnsSuccess) 121 { 122 getToUpdateCompleted(ActionStatus::success); 123 124 std::vector<std::string> testBlobs = {staticLayoutBlobId, hashBlobId}; 125 for (const auto& blob : testBlobs) 126 { 127 ASSERT_TRUE(handler->canHandleBlob(blob)); 128 129 blobs::BlobMeta meta = {}; 130 EXPECT_TRUE(handler->stat(blob, &meta)); 131 EXPECT_EQ(expectedIdleMeta, meta); 132 } 133 } 134 135 /* 136 * writemeta(session) 137 */ 138 TEST_F(FirmwareHandlerUpdateCompletedTest, WriteMetaToUpdateBlobReturnsFailure) 139 { 140 getToUpdateCompleted(ActionStatus::success); 141 142 EXPECT_FALSE(handler->writeMeta(session, 0, {0x01})); 143 } 144 145 /* 146 * write(session) 147 */ 148 TEST_F(FirmwareHandlerUpdateCompletedTest, WriteToUpdateBlobReturnsFailure) 149 { 150 getToUpdateCompleted(ActionStatus::success); 151 152 EXPECT_FALSE(handler->write(session, 0, {0x01})); 153 } 154 155 /* 156 * commit(session) - returns failure 157 */ 158 TEST_F(FirmwareHandlerUpdateCompletedTest, 159 CommitOnUpdateBlobAfterSuccessReturnsFailure) 160 { 161 getToUpdateCompleted(ActionStatus::success); 162 163 EXPECT_CALL(*updateMockPtr, trigger()).Times(0); 164 EXPECT_FALSE(handler->commit(session, {})); 165 } 166 167 TEST_F(FirmwareHandlerUpdateCompletedTest, 168 CommitOnUpdateBlobAfterFailureReturnsFailure) 169 { 170 getToUpdateCompleted(ActionStatus::failed); 171 172 EXPECT_CALL(*updateMockPtr, trigger()).Times(0); 173 EXPECT_FALSE(handler->commit(session, {})); 174 } 175 176 /* 177 * read(session) - nothing to read here. 178 */ 179 TEST_F(FirmwareHandlerUpdateCompletedTest, ReadingFromUpdateBlobReturnsNothing) 180 { 181 getToUpdateCompleted(ActionStatus::success); 182 183 EXPECT_THAT(handler->read(session, 0, 1), IsEmpty()); 184 } 185 186 /* 187 * getBlobIds 188 * canHandleBlob(blob) 189 */ 190 TEST_F(FirmwareHandlerUpdateCompletedTest, GetBlobListProvidesExpectedBlobs) 191 { 192 getToUpdateCompleted(ActionStatus::success); 193 194 EXPECT_THAT( 195 handler->getBlobIds(), 196 UnorderedElementsAreArray( 197 {updateBlobId, hashBlobId, activeImageBlobId, staticLayoutBlobId})); 198 } 199 200 /* 201 * close(session) - closes everything out and returns to state not-yet-started. 202 * It doesn't go and clean out any update artifacts that may be present on the 203 * system. It's up to the update implementation to deal with this before 204 * marking complete. 205 */ 206 TEST_F(FirmwareHandlerUpdateCompletedTest, 207 ClosingOnUpdateBlobIdAfterSuccessReturnsToNotYetStartedAndCleansBlobList) 208 { 209 getToUpdateCompleted(ActionStatus::success); 210 211 handler->close(session); 212 expectedState(FirmwareBlobHandler::UpdateState::notYetStarted); 213 214 EXPECT_THAT(handler->getBlobIds(), 215 UnorderedElementsAreArray(startingBlobs)); 216 } 217 218 TEST_F(FirmwareHandlerUpdateCompletedTest, 219 ClosingOnUpdateBlobIdAfterFailureReturnsToNotYetStartedAndCleansBlobList) 220 { 221 getToUpdateCompleted(ActionStatus::failed); 222 223 handler->close(session); 224 expectedState(FirmwareBlobHandler::UpdateState::notYetStarted); 225 226 EXPECT_THAT(handler->getBlobIds(), 227 UnorderedElementsAreArray(startingBlobs)); 228 } 229 230 /* 231 * deleteBlob(blob) 232 */ 233 TEST_F(FirmwareHandlerUpdateCompletedTest, DeleteBlobReturnsFalse) 234 { 235 /* Try deleting all blobs, it doesn't really matter which though because you 236 * cannot close out an open session, therefore you must fail to delete 237 * anything unless everything is closed. 238 */ 239 getToUpdateCompleted(ActionStatus::success); 240 241 auto blobs = handler->getBlobIds(); 242 for (const auto& b : blobs) 243 { 244 EXPECT_FALSE(handler->deleteBlob(b)); 245 } 246 } 247 248 /* 249 * expire(session) 250 */ 251 TEST_F(FirmwareHandlerUpdateCompletedTest, ExpireOnUpdateCompletedAbortsProcess) 252 { 253 getToUpdateCompleted(ActionStatus::success); 254 255 ASSERT_TRUE(handler->expire(session)); 256 EXPECT_THAT(handler->getBlobIds(), 257 UnorderedElementsAreArray(startingBlobs)); 258 259 expectedState(FirmwareBlobHandler::UpdateState::notYetStarted); 260 } 261 262 } // namespace 263 } // namespace ipmi_flash 264