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_INVALID, statBlob(&mgr, request, reply, &dataLen)); 43 } 44 45 TEST(BlobStatTest, RequestRejectedReturnsFailure) 46 { 47 // The blobId is rejected for any reason. 48 49 ManagerMock mgr; 50 size_t dataLen; 51 uint8_t request[MAX_IPMI_BUFFER] = {0}; 52 uint8_t reply[MAX_IPMI_BUFFER] = {0}; 53 auto req = reinterpret_cast<struct BmcBlobStatTx*>(request); 54 std::string blobId = "a"; 55 56 req->cmd = BlobOEMCommands::bmcBlobStat; 57 req->crc = 0; 58 // length() doesn't include the nul-terminator, request buff is initialized 59 // to 0s 60 std::memcpy(req->blobId, blobId.c_str(), blobId.length()); 61 62 dataLen = sizeof(struct BmcBlobStatTx) + blobId.length() + 1; 63 64 EXPECT_CALL(mgr, stat(Matcher<const std::string&>(StrEq(blobId)), 65 Matcher<struct BlobMeta*>(_))) 66 .WillOnce(Return(false)); 67 68 EXPECT_EQ(IPMI_CC_INVALID, statBlob(&mgr, request, reply, &dataLen)); 69 } 70 71 TEST(BlobStatTest, RequestSucceedsNoMetadata) 72 { 73 // Stat request succeeeds but there were no metadata bytes. 74 75 ManagerMock mgr; 76 size_t dataLen; 77 uint8_t request[MAX_IPMI_BUFFER] = {0}; 78 uint8_t reply[MAX_IPMI_BUFFER] = {0}; 79 auto req = reinterpret_cast<struct BmcBlobStatTx*>(request); 80 std::string blobId = "a"; 81 82 req->cmd = BlobOEMCommands::bmcBlobStat; 83 req->crc = 0; 84 // length() doesn't include the nul-terminator, request buff is initialized 85 // to 0s 86 std::memcpy(req->blobId, blobId.c_str(), blobId.length()); 87 88 dataLen = sizeof(struct BmcBlobStatTx) + blobId.length() + 1; 89 90 struct BmcBlobStatRx rep; 91 rep.crc = 0x00; 92 rep.blobState = 0x01; 93 rep.size = 0x100; 94 rep.metadataLen = 0x00; 95 96 EXPECT_CALL(mgr, stat(Matcher<const std::string&>(StrEq(blobId)), 97 Matcher<struct BlobMeta*>(NotNull()))) 98 .WillOnce(Invoke([&](const std::string& path, struct BlobMeta* meta) { 99 meta->blobState = rep.blobState; 100 meta->size = rep.size; 101 return true; 102 })); 103 104 EXPECT_EQ(IPMI_CC_OK, statBlob(&mgr, request, reply, &dataLen)); 105 106 EXPECT_EQ(sizeof(rep), dataLen); 107 EXPECT_EQ(0, std::memcmp(reply, &rep, sizeof(rep))); 108 } 109 110 TEST(BlobStatTest, RequestSucceedsWithMetadata) 111 { 112 // Stat request succeeds and there were metadata bytes. 113 114 ManagerMock mgr; 115 size_t dataLen; 116 uint8_t request[MAX_IPMI_BUFFER] = {0}; 117 uint8_t reply[MAX_IPMI_BUFFER] = {0}; 118 auto req = reinterpret_cast<struct BmcBlobStatTx*>(request); 119 std::string blobId = "a"; 120 121 req->cmd = BlobOEMCommands::bmcBlobStat; 122 req->crc = 0; 123 // length() doesn't include the nul-terminator, request buff is initialized 124 // to 0s 125 std::memcpy(req->blobId, blobId.c_str(), blobId.length()); 126 127 dataLen = sizeof(struct BmcBlobStatTx) + blobId.length() + 1; 128 129 struct BlobMeta lmeta; 130 lmeta.blobState = 0x01; 131 lmeta.size = 0x100; 132 lmeta.metadata.push_back(0x01); 133 lmeta.metadata.push_back(0x02); 134 lmeta.metadata.push_back(0x03); 135 lmeta.metadata.push_back(0x04); 136 137 struct BmcBlobStatRx rep; 138 rep.crc = 0x00; 139 rep.blobState = lmeta.blobState; 140 rep.size = lmeta.size; 141 rep.metadataLen = lmeta.metadata.size(); 142 143 EXPECT_CALL(mgr, stat(Matcher<const std::string&>(StrEq(blobId)), 144 Matcher<struct BlobMeta*>(NotNull()))) 145 .WillOnce(Invoke([&](const std::string& path, struct BlobMeta* meta) { 146 (*meta) = lmeta; 147 return true; 148 })); 149 150 EXPECT_EQ(IPMI_CC_OK, statBlob(&mgr, request, reply, &dataLen)); 151 152 EXPECT_EQ(sizeof(rep) + lmeta.metadata.size(), dataLen); 153 EXPECT_EQ(0, std::memcmp(reply, &rep, sizeof(rep))); 154 EXPECT_EQ(0, std::memcmp(reply + sizeof(rep), lmeta.metadata.data(), 155 lmeta.metadata.size())); 156 } 157 } // namespace blobs 158