1 /* The goal of these tests is to verify the behavior of all blob commands given 2 * the current state is updateStarted. This state is achieved as an exit from 3 * updatePending. 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 40 class FirmwareHandlerUpdateStartedTest : public IpmiOnlyFirmwareStaticTest 41 {}; 42 43 /* 44 * open(blob) 45 */ 46 TEST_F(FirmwareHandlerUpdateStartedTest, AttemptToOpenFilesReturnsFailure) 47 { 48 /* In state updateStarted a file is open, which means no others can be. */ 49 getToUpdateStarted(); 50 51 auto blobsToOpen = handler->getBlobIds(); 52 for (const auto& blob : blobsToOpen) 53 { 54 EXPECT_FALSE(handler->open(session + 1, flags, blob)); 55 } 56 } 57 58 /* canHandleBlob(blob) 59 * getBlobIds 60 */ 61 TEST_F(FirmwareHandlerUpdateStartedTest, VerifyListOfBlobs) 62 { 63 getToUpdateStarted(); 64 65 EXPECT_THAT( 66 handler->getBlobIds(), 67 UnorderedElementsAreArray( 68 {updateBlobId, hashBlobId, activeImageBlobId, staticLayoutBlobId})); 69 } 70 71 /* 72 * deleteBlob(blob) 73 */ 74 TEST_F(FirmwareHandlerUpdateStartedTest, DeleteBlobReturnsFalse) 75 { 76 /* Try deleting all blobs, it doesn't really matter which though because you 77 * cannot close out an open session, therefore you must fail to delete 78 * anything unless everything is closed. 79 */ 80 getToUpdateStarted(); 81 auto blobs = handler->getBlobIds(); 82 for (const auto& b : blobs) 83 { 84 EXPECT_FALSE(handler->deleteBlob(b)); 85 } 86 } 87 88 /* 89 * stat(blob) 90 */ 91 TEST_F(FirmwareHandlerUpdateStartedTest, StatOnActiveImageReturnsFailure) 92 { 93 getToUpdateStarted(); 94 95 ASSERT_TRUE(handler->canHandleBlob(activeImageBlobId)); 96 97 blobs::BlobMeta meta; 98 EXPECT_FALSE(handler->stat(activeImageBlobId, &meta)); 99 } 100 101 TEST_F(FirmwareHandlerUpdateStartedTest, StatOnUpdateBlobReturnsFailure) 102 { 103 getToUpdateStarted(); 104 105 ASSERT_TRUE(handler->canHandleBlob(updateBlobId)); 106 107 blobs::BlobMeta meta; 108 EXPECT_FALSE(handler->stat(updateBlobId, &meta)); 109 } 110 111 TEST_F(FirmwareHandlerUpdateStartedTest, StatOnNormalBlobsReturnsSuccess) 112 { 113 getToUpdateStarted(); 114 115 std::vector<std::string> testBlobs = {staticLayoutBlobId, hashBlobId}; 116 for (const auto& blob : testBlobs) 117 { 118 ASSERT_TRUE(handler->canHandleBlob(blob)); 119 120 blobs::BlobMeta meta = {}; 121 EXPECT_TRUE(handler->stat(blob, &meta)); 122 EXPECT_EQ(expectedIdleMeta, meta); 123 } 124 } 125 126 /* 127 * writemeta(session) 128 */ 129 TEST_F(FirmwareHandlerUpdateStartedTest, WriteMetaToUpdateBlobReturnsFailure) 130 { 131 getToUpdateStarted(); 132 EXPECT_FALSE(handler->writeMeta(session, 0, {0x01})); 133 } 134 135 /* 136 * write(session) 137 */ 138 TEST_F(FirmwareHandlerUpdateStartedTest, WriteToUpdateBlobReturnsFailure) 139 { 140 getToUpdateStarted(); 141 EXPECT_FALSE(handler->write(session, 0, {0x01})); 142 } 143 144 /* 145 * read(session) 146 */ 147 TEST_F(FirmwareHandlerUpdateStartedTest, ReadFromUpdateBlobReturnsEmpty) 148 { 149 getToUpdateStarted(); 150 EXPECT_THAT(handler->read(session, 0, 1), IsEmpty()); 151 } 152 153 /* 154 * commit(session) 155 */ 156 TEST_F(FirmwareHandlerUpdateStartedTest, 157 CallingCommitShouldReturnTrueAndHaveNoEffect) 158 { 159 getToUpdateStarted(); 160 EXPECT_CALL(*updateMockPtr, trigger()).Times(0); 161 162 EXPECT_TRUE(handler->commit(session, {})); 163 expectedState(FirmwareBlobHandler::UpdateState::updateStarted); 164 } 165 166 /* 167 * stat(session) - this will trigger a check, and the state may change. 168 */ 169 TEST_F(FirmwareHandlerUpdateStartedTest, 170 CallStatChecksActionStatusReturnsRunningDoesNotChangeState) 171 { 172 getToUpdateStarted(); 173 EXPECT_CALL(*updateMockPtr, status()) 174 .WillOnce(Return(ActionStatus::running)); 175 176 blobs::BlobMeta meta, expectedMeta = {}; 177 expectedMeta.size = 0; 178 expectedMeta.blobState = flags | blobs::StateFlags::committing; 179 expectedMeta.metadata.push_back( 180 static_cast<std::uint8_t>(ActionStatus::running)); 181 182 EXPECT_TRUE(handler->stat(session, &meta)); 183 EXPECT_EQ(expectedMeta, meta); 184 expectedState(FirmwareBlobHandler::UpdateState::updateStarted); 185 } 186 187 TEST_F(FirmwareHandlerUpdateStartedTest, 188 CallStatChecksActionStatusReturnsFailedChangesStateToCompleted) 189 { 190 getToUpdateStarted(); 191 EXPECT_CALL(*updateMockPtr, status()) 192 .WillOnce(Return(ActionStatus::failed)); 193 194 blobs::BlobMeta meta, expectedMeta = {}; 195 expectedMeta.size = 0; 196 expectedMeta.blobState = flags | blobs::StateFlags::commit_error; 197 expectedMeta.metadata.push_back( 198 static_cast<std::uint8_t>(ActionStatus::failed)); 199 200 EXPECT_TRUE(handler->stat(session, &meta)); 201 EXPECT_EQ(expectedMeta, meta); 202 expectedState(FirmwareBlobHandler::UpdateState::updateCompleted); 203 } 204 205 TEST_F(FirmwareHandlerUpdateStartedTest, 206 CallStatChecksActionStatusReturnsSuccessChangesStateToCompleted) 207 { 208 getToUpdateStarted(); 209 EXPECT_CALL(*updateMockPtr, status()) 210 .WillOnce(Return(ActionStatus::success)); 211 212 blobs::BlobMeta meta, expectedMeta = {}; 213 expectedMeta.size = 0; 214 expectedMeta.blobState = flags | blobs::StateFlags::committed; 215 expectedMeta.metadata.push_back( 216 static_cast<std::uint8_t>(ActionStatus::success)); 217 218 EXPECT_TRUE(handler->stat(session, &meta)); 219 EXPECT_EQ(expectedMeta, meta); 220 expectedState(FirmwareBlobHandler::UpdateState::updateCompleted); 221 } 222 223 /* 224 * close(session) - this will abort. 225 */ 226 TEST_F(FirmwareHandlerUpdateStartedTest, CloseOnUpdateDuringUpdateAbortsProcess) 227 { 228 getToUpdateStarted(); 229 EXPECT_CALL(*updateMockPtr, abort()).Times(1); 230 231 EXPECT_TRUE(handler->close(session)); 232 233 EXPECT_THAT(handler->getBlobIds(), 234 UnorderedElementsAreArray(startingBlobs)); 235 236 expectedState(FirmwareBlobHandler::UpdateState::notYetStarted); 237 } 238 239 /* 240 * expire(session) 241 */ 242 TEST_F(FirmwareHandlerUpdateStartedTest, 243 ExpireOnUpdateDuringUpdateAbortsProcess) 244 { 245 getToUpdateStarted(); 246 EXPECT_CALL(*updateMockPtr, abort()).Times(0); 247 248 ASSERT_TRUE(handler->expire(session)); 249 250 EXPECT_THAT(handler->getBlobIds(), 251 UnorderedElementsAreArray(startingBlobs)); 252 253 expectedState(FirmwareBlobHandler::UpdateState::notYetStarted); 254 } 255 256 } // namespace 257 } // namespace ipmi_flash 258