1 #include "extensions/openpower-pels/data_interface.hpp" 2 #include "extensions/openpower-pels/host_interface.hpp" 3 #include "extensions/openpower-pels/journal.hpp" 4 5 #include <fcntl.h> 6 7 #include <sdeventplus/source/io.hpp> 8 9 #include <filesystem> 10 11 #include <gmock/gmock.h> 12 13 namespace openpower 14 { 15 namespace pels 16 { 17 18 class MockDataInterface : public DataInterfaceBase 19 { 20 public: 21 MockDataInterface() {} 22 MOCK_METHOD(std::string, getMachineTypeModel, (), (const override)); 23 MOCK_METHOD(std::string, getMachineSerialNumber, (), (const override)); 24 MOCK_METHOD(std::string, getServerFWVersion, (), (const override)); 25 MOCK_METHOD(std::string, getBMCFWVersion, (), (const override)); 26 MOCK_METHOD(std::string, getBMCFWVersionID, (), (const override)); 27 MOCK_METHOD(bool, getHostPELEnablement, (), (const override)); 28 MOCK_METHOD(std::string, getBMCState, (), (const override)); 29 MOCK_METHOD(std::string, getChassisState, (), (const override)); 30 MOCK_METHOD(std::string, getHostState, (), (const override)); 31 MOCK_METHOD(std::string, getMotherboardCCIN, (), (const override)); 32 MOCK_METHOD(void, getHWCalloutFields, 33 (const std::string&, std::string&, std::string&, std::string&), 34 (const override)); 35 MOCK_METHOD(std::string, getLocationCode, (const std::string&), 36 (const override)); 37 MOCK_METHOD(std::vector<std::string>, getSystemNames, (), (const override)); 38 MOCK_METHOD(std::string, expandLocationCode, (const std::string&, uint16_t), 39 (const override)); 40 MOCK_METHOD(std::string, getInventoryFromLocCode, 41 (const std::string&, uint16_t, bool), (const override)); 42 MOCK_METHOD(void, assertLEDGroup, (const std::string&, bool), 43 (const override)); 44 MOCK_METHOD(void, setFunctional, (const std::string&, bool), 45 (const override)); 46 MOCK_METHOD(std::vector<uint8_t>, getSystemIMKeyword, (), (const override)); 47 MOCK_METHOD(bool, getQuiesceOnError, (), (const override)); 48 MOCK_METHOD(void, setCriticalAssociation, (const std::string&), 49 (const override)); 50 MOCK_METHOD(std::vector<bool>, checkDumpStatus, 51 (const std::vector<std::string>&), (const override)); 52 MOCK_METHOD(std::string, getBootState, (), (const override)); 53 MOCK_METHOD(void, createGuardRecord, 54 (const std::vector<uint8_t>&, const std::string&, 55 const std::string&), 56 (const override)); 57 MOCK_METHOD(void, createProgressSRC, 58 (const uint64_t&, const std::vector<uint8_t>&), 59 (const override)); 60 MOCK_METHOD(std::vector<uint32_t>, getLogIDWithHwIsolation, (), 61 (const override)); 62 MOCK_METHOD(std::vector<uint8_t>, getRawProgressSRC, (), (const override)); 63 64 void changeHostState(bool newState) 65 { 66 setHostUp(newState); 67 } 68 69 void setHMCManaged(bool managed) 70 { 71 _hmcManaged = managed; 72 } 73 }; 74 75 /** 76 * @brief The mock HostInterface class 77 * 78 * This replaces the PLDM calls with a FIFO for the asynchronous 79 * responses. 80 */ 81 class MockHostInterface : public HostInterface 82 { 83 public: 84 /** 85 * @brief Constructor 86 * 87 * @param[in] event - The sd_event object 88 * @param[in] dataIface - The DataInterface class 89 */ 90 MockHostInterface(sd_event* event, DataInterfaceBase& dataIface) : 91 HostInterface(event, dataIface) 92 { 93 char templ[] = "/tmp/cmdfifoXXXXXX"; 94 std::filesystem::path dir = mkdtemp(templ); 95 _fifo = dir / "fifo"; 96 } 97 98 /** 99 * @brief Destructor 100 */ 101 virtual ~MockHostInterface() 102 { 103 std::filesystem::remove_all(_fifo.parent_path()); 104 } 105 106 MOCK_METHOD(CmdStatus, sendNewLogCmd, (uint32_t, uint32_t), (override)); 107 108 /** 109 * @brief Cancels waiting for a command response 110 */ 111 virtual void cancelCmd() override 112 { 113 _inProgress = false; 114 _source = nullptr; 115 } 116 117 /** 118 * @brief Returns the amount of time to wait before retrying after 119 * a failed send command. 120 * 121 * @return milliseconds - The amount of time to wait 122 */ 123 virtual std::chrono::milliseconds getSendRetryDelay() const override 124 { 125 return std::chrono::milliseconds(2); 126 } 127 128 /** 129 * @brief Returns the amount of time to wait before retrying after 130 * a command receive. 131 * 132 * @return milliseconds - The amount of time to wait 133 */ 134 virtual std::chrono::milliseconds getReceiveRetryDelay() const override 135 { 136 return std::chrono::milliseconds(2); 137 } 138 139 /** 140 * @brief Returns the amount of time to wait before retrying if the 141 * host firmware's PEL storage was full and it can't store 142 * any more logs until it is freed up somehow. 143 * 144 * @return milliseconds - The amount of time to wait 145 */ 146 virtual std::chrono::milliseconds getHostFullRetryDelay() const override 147 { 148 return std::chrono::milliseconds(400); 149 } 150 151 /** 152 * @brief Returns the amount of time to wait after the host is up 153 * before sending commands. 154 * 155 * @return milliseconds - The amount of time to wait 156 */ 157 virtual std::chrono::milliseconds getHostUpDelay() const override 158 { 159 return std::chrono::milliseconds(0); 160 } 161 162 /** 163 * @brief Returns the number of commands processed 164 */ 165 size_t numCmdsProcessed() const 166 { 167 return _cmdsProcessed; 168 } 169 170 /** 171 * @brief Writes the data passed in to the FIFO 172 * 173 * @param[in] hostResponse - use a 0 to indicate success 174 * 175 * @return CmdStatus - success or failure 176 */ 177 CmdStatus send(uint8_t hostResponse) 178 { 179 // Create a FIFO once. 180 if (!std::filesystem::exists(_fifo)) 181 { 182 if (mkfifo(_fifo.c_str(), 0622)) 183 { 184 ADD_FAILURE() << "Failed mkfifo " << _fifo << strerror(errno); 185 exit(-1); 186 } 187 } 188 189 // Open it and register the reponse callback to 190 // be used on FD activity. 191 int fd = open(_fifo.c_str(), O_NONBLOCK | O_RDWR); 192 EXPECT_TRUE(fd >= 0) << "Unable to open FIFO"; 193 194 auto callback = [this](sdeventplus::source::IO& source, int fd, 195 uint32_t events) { 196 this->receive(source, fd, events); 197 }; 198 199 try 200 { 201 _source = std::make_unique<sdeventplus::source::IO>( 202 _event, fd, EPOLLIN, 203 std::bind(callback, std::placeholders::_1, 204 std::placeholders::_2, std::placeholders::_3)); 205 } 206 catch (const std::exception& e) 207 { 208 ADD_FAILURE() << "Event exception: " << e.what(); 209 close(fd); 210 return CmdStatus::failure; 211 } 212 213 // Write the fake host reponse to the FIFO 214 auto bytesWritten = write(fd, &hostResponse, sizeof(hostResponse)); 215 EXPECT_EQ(bytesWritten, sizeof(hostResponse)); 216 217 _inProgress = true; 218 219 return CmdStatus::success; 220 } 221 222 protected: 223 /** 224 * @brief Reads the data written to the fifo and then calls 225 * the subscriber's callback. 226 * 227 * Nonzero data indicates a command failure (for testing bad path). 228 * 229 * @param[in] source - The event source object 230 * @param[in] fd - The file descriptor used 231 * @param[in] events - The event bits 232 */ 233 void receive(sdeventplus::source::IO& /*source*/, int /*fd*/, 234 uint32_t events) override 235 { 236 if (!(events & EPOLLIN)) 237 { 238 return; 239 } 240 241 _inProgress = false; 242 243 int newFD = open(_fifo.c_str(), O_NONBLOCK | O_RDONLY); 244 ASSERT_TRUE(newFD >= 0) << "Failed to open FIFO"; 245 246 // Read the host success/failure response from the FIFO. 247 uint8_t data; 248 auto bytesRead = read(newFD, &data, sizeof(data)); 249 EXPECT_EQ(bytesRead, sizeof(data)); 250 251 close(newFD); 252 253 ResponseStatus status = ResponseStatus::success; 254 if (data != 0) 255 { 256 status = ResponseStatus::failure; 257 } 258 259 callResponseFunc(status); 260 261 // Keep account of the number of commands responses for testing. 262 _cmdsProcessed++; 263 } 264 265 private: 266 /** 267 * @brief The event source for the fifo 268 */ 269 std::unique_ptr<sdeventplus::source::IO> _source; 270 271 /** 272 * @brief the path to the fifo 273 */ 274 std::filesystem::path _fifo; 275 276 /** 277 * @brief The number of commands processed 278 */ 279 size_t _cmdsProcessed = 0; 280 }; 281 282 class MockJournal : public JournalBase 283 { 284 public: 285 MockJournal() {} 286 287 MOCK_METHOD(std::vector<std::string>, getMessages, 288 (const std::string&, size_t), (const override)); 289 290 MOCK_METHOD(void, sync, (), (const override)); 291 }; 292 293 } // namespace pels 294 } // namespace openpower 295