1 #include "ipmi.hpp" 2 #include "manager_mock.hpp" 3 4 #include <cstring> 5 #include <string> 6 7 #include <gtest/gtest.h> 8 9 namespace blobs 10 { 11 12 using ::testing::_; 13 using ::testing::Invoke; 14 using ::testing::Matcher; 15 using ::testing::NotNull; 16 using ::testing::Return; 17 using ::testing::StrEq; 18 19 // ipmid.hpp isn't installed where we can grab it and this value is per BMC 20 // SoC. 21 #define MAX_IPMI_BUFFER 64 22 23 TEST(BlobStatTest, InvalidRequestLengthReturnsFailure) 24 { 25 // There is a minimum blobId length of one character, this test verifies 26 // we check that. 27 28 ManagerMock mgr; 29 size_t dataLen; 30 uint8_t request[MAX_IPMI_BUFFER] = {0}; 31 uint8_t reply[MAX_IPMI_BUFFER] = {0}; 32 auto req = reinterpret_cast<struct BmcBlobStatTx*>(request); 33 std::string blobId = "abc"; 34 35 req->cmd = static_cast<std::uint8_t>(BlobOEMCommands::bmcBlobStat); 36 req->crc = 0; 37 // length() doesn't include the nul-terminator. 38 std::memcpy(req + 1, blobId.c_str(), blobId.length()); 39 40 dataLen = sizeof(struct BmcBlobStatTx) + blobId.length(); 41 42 EXPECT_EQ(IPMI_CC_REQ_DATA_LEN_INVALID, 43 statBlob(&mgr, request, reply, &dataLen)); 44 } 45 46 TEST(BlobStatTest, RequestRejectedReturnsFailure) 47 { 48 // The blobId is rejected for any reason. 49 50 ManagerMock mgr; 51 size_t dataLen; 52 uint8_t request[MAX_IPMI_BUFFER] = {0}; 53 uint8_t reply[MAX_IPMI_BUFFER] = {0}; 54 auto req = reinterpret_cast<struct BmcBlobStatTx*>(request); 55 std::string blobId = "a"; 56 57 req->cmd = static_cast<std::uint8_t>(BlobOEMCommands::bmcBlobStat); 58 req->crc = 0; 59 // length() doesn't include the nul-terminator, request buff is initialized 60 // to 0s 61 std::memcpy(req + 1, blobId.c_str(), blobId.length()); 62 63 dataLen = sizeof(struct BmcBlobStatTx) + blobId.length() + 1; 64 65 EXPECT_CALL(mgr, stat(Matcher<const std::string&>(StrEq(blobId)), 66 Matcher<BlobMeta*>(_))) 67 .WillOnce(Return(false)); 68 69 EXPECT_EQ(IPMI_CC_UNSPECIFIED_ERROR, 70 statBlob(&mgr, request, reply, &dataLen)); 71 } 72 73 TEST(BlobStatTest, RequestSucceedsNoMetadata) 74 { 75 // Stat request succeeeds but there were no metadata bytes. 76 77 ManagerMock mgr; 78 size_t dataLen; 79 uint8_t request[MAX_IPMI_BUFFER] = {0}; 80 uint8_t reply[MAX_IPMI_BUFFER] = {0}; 81 auto req = reinterpret_cast<struct BmcBlobStatTx*>(request); 82 std::string blobId = "a"; 83 84 req->cmd = static_cast<std::uint8_t>(BlobOEMCommands::bmcBlobStat); 85 req->crc = 0; 86 // length() doesn't include the nul-terminator, request buff is initialized 87 // to 0s 88 std::memcpy(req + 1, blobId.c_str(), blobId.length()); 89 90 dataLen = sizeof(struct BmcBlobStatTx) + blobId.length() + 1; 91 92 struct BmcBlobStatRx rep; 93 rep.crc = 0x00; 94 rep.blobState = 0x01; 95 rep.size = 0x100; 96 rep.metadataLen = 0x00; 97 98 uint16_t blobState = rep.blobState; 99 uint32_t size = rep.size; 100 101 EXPECT_CALL(mgr, stat(Matcher<const std::string&>(StrEq(blobId)), 102 Matcher<BlobMeta*>(NotNull()))) 103 .WillOnce(Invoke([&](const std::string&, BlobMeta* meta) { 104 meta->blobState = blobState; 105 meta->size = size; 106 return true; 107 })); 108 109 EXPECT_EQ(IPMI_CC_OK, statBlob(&mgr, request, reply, &dataLen)); 110 111 EXPECT_EQ(sizeof(rep), dataLen); 112 EXPECT_EQ(0, std::memcmp(reply, &rep, sizeof(rep))); 113 } 114 115 TEST(BlobStatTest, RequestSucceedsWithMetadata) 116 { 117 // Stat request succeeds and there were metadata bytes. 118 119 ManagerMock mgr; 120 size_t dataLen; 121 uint8_t request[MAX_IPMI_BUFFER] = {0}; 122 uint8_t reply[MAX_IPMI_BUFFER] = {0}; 123 auto req = reinterpret_cast<struct BmcBlobStatTx*>(request); 124 std::string blobId = "a"; 125 126 req->cmd = static_cast<std::uint8_t>(BlobOEMCommands::bmcBlobStat); 127 req->crc = 0; 128 // length() doesn't include the nul-terminator, request buff is initialized 129 // to 0s 130 std::memcpy(req + 1, blobId.c_str(), blobId.length()); 131 132 dataLen = sizeof(struct BmcBlobStatTx) + blobId.length() + 1; 133 134 BlobMeta lmeta; 135 lmeta.blobState = 0x01; 136 lmeta.size = 0x100; 137 lmeta.metadata.push_back(0x01); 138 lmeta.metadata.push_back(0x02); 139 lmeta.metadata.push_back(0x03); 140 lmeta.metadata.push_back(0x04); 141 142 struct BmcBlobStatRx rep; 143 rep.crc = 0x00; 144 rep.blobState = lmeta.blobState; 145 rep.size = lmeta.size; 146 rep.metadataLen = lmeta.metadata.size(); 147 148 EXPECT_CALL(mgr, stat(Matcher<const std::string&>(StrEq(blobId)), 149 Matcher<BlobMeta*>(NotNull()))) 150 .WillOnce(Invoke([&](const std::string&, BlobMeta* meta) { 151 (*meta) = lmeta; 152 return true; 153 })); 154 155 EXPECT_EQ(IPMI_CC_OK, statBlob(&mgr, request, reply, &dataLen)); 156 157 EXPECT_EQ(sizeof(rep) + lmeta.metadata.size(), dataLen); 158 EXPECT_EQ(0, std::memcmp(reply, &rep, sizeof(rep))); 159 EXPECT_EQ(0, std::memcmp(reply + sizeof(rep), lmeta.metadata.data(), 160 lmeta.metadata.size())); 161 } 162 } // namespace blobs 163