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 = BlobOEMCommands::bmcBlobStat; 36 req->crc = 0; 37 // length() doesn't include the nul-terminator. 38 std::memcpy(req->blobId, 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 = 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->blobId, 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<struct 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 = 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->blobId, 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 EXPECT_CALL(mgr, stat(Matcher<const std::string&>(StrEq(blobId)), 99 Matcher<struct BlobMeta*>(NotNull()))) 100 .WillOnce(Invoke([&](const std::string& path, struct BlobMeta* meta) { 101 meta->blobState = rep.blobState; 102 meta->size = rep.size; 103 return true; 104 })); 105 106 EXPECT_EQ(IPMI_CC_OK, statBlob(&mgr, request, reply, &dataLen)); 107 108 EXPECT_EQ(sizeof(rep), dataLen); 109 EXPECT_EQ(0, std::memcmp(reply, &rep, sizeof(rep))); 110 } 111 112 TEST(BlobStatTest, RequestSucceedsWithMetadata) 113 { 114 // Stat request succeeds and there were metadata bytes. 115 116 ManagerMock mgr; 117 size_t dataLen; 118 uint8_t request[MAX_IPMI_BUFFER] = {0}; 119 uint8_t reply[MAX_IPMI_BUFFER] = {0}; 120 auto req = reinterpret_cast<struct BmcBlobStatTx*>(request); 121 std::string blobId = "a"; 122 123 req->cmd = BlobOEMCommands::bmcBlobStat; 124 req->crc = 0; 125 // length() doesn't include the nul-terminator, request buff is initialized 126 // to 0s 127 std::memcpy(req->blobId, blobId.c_str(), blobId.length()); 128 129 dataLen = sizeof(struct BmcBlobStatTx) + blobId.length() + 1; 130 131 struct BlobMeta lmeta; 132 lmeta.blobState = 0x01; 133 lmeta.size = 0x100; 134 lmeta.metadata.push_back(0x01); 135 lmeta.metadata.push_back(0x02); 136 lmeta.metadata.push_back(0x03); 137 lmeta.metadata.push_back(0x04); 138 139 struct BmcBlobStatRx rep; 140 rep.crc = 0x00; 141 rep.blobState = lmeta.blobState; 142 rep.size = lmeta.size; 143 rep.metadataLen = lmeta.metadata.size(); 144 145 EXPECT_CALL(mgr, stat(Matcher<const std::string&>(StrEq(blobId)), 146 Matcher<struct BlobMeta*>(NotNull()))) 147 .WillOnce(Invoke([&](const std::string& path, struct BlobMeta* meta) { 148 (*meta) = lmeta; 149 return true; 150 })); 151 152 EXPECT_EQ(IPMI_CC_OK, statBlob(&mgr, request, reply, &dataLen)); 153 154 EXPECT_EQ(sizeof(rep) + lmeta.metadata.size(), dataLen); 155 EXPECT_EQ(0, std::memcmp(reply, &rep, sizeof(rep))); 156 EXPECT_EQ(0, std::memcmp(reply + sizeof(rep), lmeta.metadata.data(), 157 lmeta.metadata.size())); 158 } 159 } // namespace blobs 160