1 #include "libpldmresponder/file_io.hpp" 2 3 #include "libpldm/base.h" 4 #include "libpldm/file_io.h" 5 6 #include <gmock/gmock-matchers.h> 7 #include <gmock/gmock.h> 8 #include <gtest/gtest.h> 9 #define SD_JOURNAL_SUPPRESS_LOCATION 10 11 #include <systemd/sd-journal.h> 12 13 std::vector<std::string> logs; 14 15 extern "C" { 16 17 int sd_journal_send(const char* format, ...) 18 { 19 logs.push_back(format); 20 return 0; 21 } 22 23 int sd_journal_send_with_location(const char* file, const char* line, 24 const char* func, const char* format, ...) 25 { 26 logs.push_back(format); 27 return 0; 28 } 29 } 30 31 namespace pldm 32 { 33 34 namespace responder 35 { 36 37 namespace dma 38 { 39 40 class MockDMA 41 { 42 public: 43 MOCK_METHOD5(transferDataHost, 44 int(const fs::path& file, uint32_t offset, uint32_t length, 45 uint64_t address, bool upstream)); 46 }; 47 48 } // namespace dma 49 } // namespace responder 50 } // namespace pldm 51 using namespace pldm::responder; 52 using ::testing::_; 53 using ::testing::Return; 54 55 TEST(TransferDataHost, GoodPath) 56 { 57 using namespace pldm::responder::dma; 58 59 MockDMA dmaObj; 60 fs::path path(""); 61 62 // Minimum length of 16 and expect transferDataHost to be called once 63 // returns the default value of 0 (the return type of transferDataHost is 64 // int, the default value for int is 0) 65 uint32_t length = minSize; 66 EXPECT_CALL(dmaObj, transferDataHost(path, 0, length, 0, true)).Times(1); 67 auto response = transferAll<MockDMA>(&dmaObj, PLDM_READ_FILE_INTO_MEMORY, 68 path, 0, length, 0, true); 69 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data()); 70 ASSERT_EQ(responsePtr->payload[0], PLDM_SUCCESS); 71 ASSERT_EQ(0, memcmp(responsePtr->payload + sizeof(responsePtr->payload[0]), 72 &length, sizeof(length))); 73 74 // maxsize of DMA 75 length = maxSize; 76 EXPECT_CALL(dmaObj, transferDataHost(path, 0, length, 0, true)).Times(1); 77 response = transferAll<MockDMA>(&dmaObj, PLDM_READ_FILE_INTO_MEMORY, path, 78 0, length, 0, true); 79 responsePtr = reinterpret_cast<pldm_msg*>(response.data()); 80 ASSERT_EQ(responsePtr->payload[0], PLDM_SUCCESS); 81 ASSERT_EQ(0, memcmp(responsePtr->payload + sizeof(responsePtr->payload[0]), 82 &length, sizeof(length))); 83 84 // length greater than maxsize of DMA 85 length = maxSize + minSize; 86 EXPECT_CALL(dmaObj, transferDataHost(path, 0, maxSize, 0, true)).Times(1); 87 EXPECT_CALL(dmaObj, transferDataHost(path, maxSize, minSize, maxSize, true)) 88 .Times(1); 89 response = transferAll<MockDMA>(&dmaObj, PLDM_READ_FILE_INTO_MEMORY, path, 90 0, length, 0, true); 91 responsePtr = reinterpret_cast<pldm_msg*>(response.data()); 92 ASSERT_EQ(responsePtr->payload[0], PLDM_SUCCESS); 93 ASSERT_EQ(0, memcmp(responsePtr->payload + sizeof(responsePtr->payload[0]), 94 &length, sizeof(length))); 95 96 // length greater than 2*maxsize of DMA 97 length = 3 * maxSize; 98 EXPECT_CALL(dmaObj, transferDataHost(_, _, _, _, true)).Times(3); 99 response = transferAll<MockDMA>(&dmaObj, PLDM_READ_FILE_INTO_MEMORY, path, 100 0, length, 0, true); 101 responsePtr = reinterpret_cast<pldm_msg*>(response.data()); 102 ASSERT_EQ(responsePtr->payload[0], PLDM_SUCCESS); 103 ASSERT_EQ(0, memcmp(responsePtr->payload + sizeof(responsePtr->payload[0]), 104 &length, sizeof(length))); 105 106 // check for downstream(copy data from host to BMC) parameter 107 length = minSize; 108 EXPECT_CALL(dmaObj, transferDataHost(path, 0, length, 0, false)).Times(1); 109 response = transferAll<MockDMA>(&dmaObj, PLDM_READ_FILE_INTO_MEMORY, path, 110 0, length, 0, false); 111 responsePtr = reinterpret_cast<pldm_msg*>(response.data()); 112 ASSERT_EQ(responsePtr->payload[0], PLDM_SUCCESS); 113 ASSERT_EQ(0, memcmp(responsePtr->payload + sizeof(responsePtr->payload[0]), 114 &length, sizeof(length))); 115 } 116 117 TEST(TransferDataHost, BadPath) 118 { 119 using namespace pldm::responder::dma; 120 121 MockDMA dmaObj; 122 fs::path path(""); 123 124 // Minimum length of 16 and transferDataHost returning a negative errno 125 uint32_t length = minSize; 126 EXPECT_CALL(dmaObj, transferDataHost(_, _, _, _, _)).WillOnce(Return(-1)); 127 auto response = transferAll<MockDMA>(&dmaObj, PLDM_READ_FILE_INTO_MEMORY, 128 path, 0, length, 0, true); 129 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data()); 130 ASSERT_EQ(responsePtr->payload[0], PLDM_ERROR); 131 132 // length greater than maxsize of DMA and transferDataHost returning a 133 // negative errno 134 length = maxSize + minSize; 135 EXPECT_CALL(dmaObj, transferDataHost(_, _, _, _, _)).WillOnce(Return(-1)); 136 response = transferAll<MockDMA>(&dmaObj, PLDM_READ_FILE_INTO_MEMORY, path, 137 0, length, 0, true); 138 responsePtr = reinterpret_cast<pldm_msg*>(response.data()); 139 ASSERT_EQ(responsePtr->payload[0], PLDM_ERROR); 140 } 141 142 TEST(ReadFileIntoMemory, BadPath) 143 { 144 uint32_t fileHandle = 0; 145 uint32_t offset = 0; 146 uint32_t length = 10; 147 uint64_t address = 0; 148 149 std::array<uint8_t, PLDM_RW_FILE_MEM_REQ_BYTES> requestMsg{}; 150 memcpy(requestMsg.data(), &fileHandle, sizeof(fileHandle)); 151 memcpy(requestMsg.data() + sizeof(fileHandle), &offset, sizeof(offset)); 152 memcpy(requestMsg.data() + sizeof(fileHandle) + sizeof(offset), &length, 153 sizeof(length)); 154 memcpy(requestMsg.data() + sizeof(fileHandle) + sizeof(offset) + 155 sizeof(length), 156 &address, sizeof(address)); 157 158 // Pass invalid payload length 159 auto response = readFileIntoMemory(requestMsg.data(), 0); 160 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data()); 161 ASSERT_EQ(responsePtr->payload[0], PLDM_ERROR_INVALID_LENGTH); 162 } 163 164 TEST(WriteFileFromMemory, BadPath) 165 { 166 uint32_t fileHandle = 0; 167 uint32_t offset = 0; 168 uint32_t length = 10; 169 uint64_t address = 0; 170 171 std::array<uint8_t, PLDM_RW_FILE_MEM_REQ_BYTES> requestMsg{}; 172 memcpy(requestMsg.data(), &fileHandle, sizeof(fileHandle)); 173 memcpy(requestMsg.data() + sizeof(fileHandle), &offset, sizeof(offset)); 174 memcpy(requestMsg.data() + sizeof(fileHandle) + sizeof(offset), &length, 175 sizeof(length)); 176 memcpy(requestMsg.data() + sizeof(fileHandle) + sizeof(offset) + 177 sizeof(length), 178 &address, sizeof(address)); 179 180 // Pass invalid payload length 181 auto response = writeFileFromMemory(requestMsg.data(), 0); 182 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data()); 183 ASSERT_EQ(responsePtr->payload[0], PLDM_ERROR_INVALID_LENGTH); 184 185 // The length field is not a multiple of DMA minsize 186 response = writeFileFromMemory(requestMsg.data(), requestMsg.size()); 187 responsePtr = reinterpret_cast<pldm_msg*>(response.data()); 188 ASSERT_EQ(responsePtr->payload[0], PLDM_INVALID_WRITE_LENGTH); 189 } 190