109d6400fSMatt Spinler #include "extensions/openpower-pels/data_interface.hpp" 2f60ac27eSMatt Spinler #include "extensions/openpower-pels/host_interface.hpp" 3d96fa60dSMatt Spinler #include "extensions/openpower-pels/journal.hpp" 4f60ac27eSMatt Spinler 5f60ac27eSMatt Spinler #include <fcntl.h> 6f60ac27eSMatt Spinler 7f60ac27eSMatt Spinler #include <sdeventplus/source/io.hpp> 809d6400fSMatt Spinler 92544b419SPatrick Williams #include <filesystem> 102544b419SPatrick Williams 1109d6400fSMatt Spinler #include <gmock/gmock.h> 1209d6400fSMatt Spinler 1309d6400fSMatt Spinler namespace openpower 1409d6400fSMatt Spinler { 1509d6400fSMatt Spinler namespace pels 1609d6400fSMatt Spinler { 1709d6400fSMatt Spinler 1809d6400fSMatt Spinler class MockDataInterface : public DataInterfaceBase 1909d6400fSMatt Spinler { 2009d6400fSMatt Spinler public: MockDataInterface()21784b02e7SMatt Spinler MockDataInterface() 22784b02e7SMatt Spinler { 23784b02e7SMatt Spinler ON_CALL(*this, checkDumpStatus) 24784b02e7SMatt Spinler .WillByDefault( 25784b02e7SMatt Spinler ::testing::Return(std::vector<bool>({false, false, false}))); 26784b02e7SMatt Spinler } 27784b02e7SMatt Spinler 28f60ac27eSMatt Spinler MOCK_METHOD(std::string, getMachineTypeModel, (), (const override)); 29f60ac27eSMatt Spinler MOCK_METHOD(std::string, getMachineSerialNumber, (), (const override)); 30f60ac27eSMatt Spinler MOCK_METHOD(std::string, getServerFWVersion, (), (const override)); 31f60ac27eSMatt Spinler MOCK_METHOD(std::string, getBMCFWVersion, (), (const override)); 32677381b8SMatt Spinler MOCK_METHOD(std::string, getBMCFWVersionID, (), (const override)); 3324a8558bSMatt Spinler MOCK_METHOD(bool, getHostPELEnablement, (), (const override)); 344aa23a1fSMatt Spinler MOCK_METHOD(std::string, getBMCState, (), (const override)); 354aa23a1fSMatt Spinler MOCK_METHOD(std::string, getChassisState, (), (const override)); 364aa23a1fSMatt Spinler MOCK_METHOD(std::string, getHostState, (), (const override)); 37075e5bafSMatt Spinler MOCK_METHOD(std::string, getMotherboardCCIN, (), (const override)); 3860c4e797SMatt Spinler MOCK_METHOD(void, getHWCalloutFields, 399b90e2a2SMatt Spinler (const std::string&, std::string&, std::string&, std::string&), 4060c4e797SMatt Spinler (const override)); 419b90e2a2SMatt Spinler MOCK_METHOD(std::string, getLocationCode, (const std::string&), 429b90e2a2SMatt Spinler (const override)); 431ab6696fSMatt Spinler MOCK_METHOD(std::vector<std::string>, getSystemNames, (), (const override)); 445fb24c11SMatt Spinler MOCK_METHOD(std::string, expandLocationCode, (const std::string&, uint16_t), 455fb24c11SMatt Spinler (const override)); 46bad056beSMatt Spinler MOCK_METHOD(std::vector<std::string>, getInventoryFromLocCode, 472f9225a4SMatt Spinler (const std::string&, uint16_t, bool), (const override)); 4834a904cfSMatt Spinler MOCK_METHOD(void, assertLEDGroup, (const std::string&, bool), 4934a904cfSMatt Spinler (const override)); 50993168deSMatt Spinler MOCK_METHOD(void, setFunctional, (const std::string&, bool), 51993168deSMatt Spinler (const override)); 52e32b7e76SBen Tyner MOCK_METHOD(std::vector<uint8_t>, getSystemIMKeyword, (), (const override)); 533b8ed7f2SSumit Kumar MOCK_METHOD(bool, getQuiesceOnError, (), (const override)); 5476198a2eSSumit Kumar MOCK_METHOD(void, setCriticalAssociation, (const std::string&), 5576198a2eSSumit Kumar (const override)); 569d43a727SSumit Kumar MOCK_METHOD(std::vector<bool>, checkDumpStatus, 579d43a727SSumit Kumar (const std::vector<std::string>&), (const override)); 582c36fddcSSumit Kumar MOCK_METHOD(std::string, getBootState, (), (const override)); 59ecaa2fceSJayanth Othayoth MOCK_METHOD(void, createGuardRecord, 60ecaa2fceSJayanth Othayoth (const std::vector<uint8_t>&, const std::string&, 61ecaa2fceSJayanth Othayoth const std::string&), 62ecaa2fceSJayanth Othayoth (const override)); 633e274432SSumit Kumar MOCK_METHOD(void, createProgressSRC, 643e274432SSumit Kumar (const uint64_t&, const std::vector<uint8_t>&), 653e274432SSumit Kumar (const override)); 66027bf285SSumit Kumar MOCK_METHOD(std::vector<uint32_t>, getLogIDWithHwIsolation, (), 67027bf285SSumit Kumar (const override)); 68875b6c7bSVijay Lobo MOCK_METHOD(std::vector<uint8_t>, getRawProgressSRC, (), (const override)); 69d8ae618aSArya K Padman MOCK_METHOD(std::optional<std::vector<uint8_t>>, getDIProperty, 70d8ae618aSArya K Padman (const std::string&), (const override)); 71*d763db35Sharsh-agarwal1 MOCK_METHOD(DBusPathList, getAssociatedPaths, 72*d763db35Sharsh-agarwal1 (const DBusPath&, const DBusPath&, int32_t, 73*d763db35Sharsh-agarwal1 const DBusInterfaceList&), 74*d763db35Sharsh-agarwal1 (const override)); 7534a904cfSMatt Spinler changeHostState(bool newState)76f60ac27eSMatt Spinler void changeHostState(bool newState) 77f60ac27eSMatt Spinler { 784aa23a1fSMatt Spinler setHostUp(newState); 79f60ac27eSMatt Spinler } 80f60ac27eSMatt Spinler setHMCManaged(bool managed)81f60ac27eSMatt Spinler void setHMCManaged(bool managed) 82f60ac27eSMatt Spinler { 83f60ac27eSMatt Spinler _hmcManaged = managed; 84f60ac27eSMatt Spinler } 850dd22c83SMatt Spinler fruPresent(const std::string & locationCode)860dd22c83SMatt Spinler void fruPresent(const std::string& locationCode) 870dd22c83SMatt Spinler { 880dd22c83SMatt Spinler setFruPresent(locationCode); 890dd22c83SMatt Spinler } 90f60ac27eSMatt Spinler }; 91f60ac27eSMatt Spinler 92f60ac27eSMatt Spinler /** 93f60ac27eSMatt Spinler * @brief The mock HostInterface class 945342d9adSMatt Spinler * 955342d9adSMatt Spinler * This replaces the PLDM calls with a FIFO for the asynchronous 965342d9adSMatt Spinler * responses. 97f60ac27eSMatt Spinler */ 98f60ac27eSMatt Spinler class MockHostInterface : public HostInterface 99f60ac27eSMatt Spinler { 100f60ac27eSMatt Spinler public: 1015342d9adSMatt Spinler /** 1025342d9adSMatt Spinler * @brief Constructor 1035342d9adSMatt Spinler * 1045342d9adSMatt Spinler * @param[in] event - The sd_event object 1055342d9adSMatt Spinler * @param[in] dataIface - The DataInterface class 1065342d9adSMatt Spinler */ MockHostInterface(sd_event * event,DataInterfaceBase & dataIface)107f60ac27eSMatt Spinler MockHostInterface(sd_event* event, DataInterfaceBase& dataIface) : 108f60ac27eSMatt Spinler HostInterface(event, dataIface) 109f60ac27eSMatt Spinler { 1105342d9adSMatt Spinler char templ[] = "/tmp/cmdfifoXXXXXX"; 1115342d9adSMatt Spinler std::filesystem::path dir = mkdtemp(templ); 1125342d9adSMatt Spinler _fifo = dir / "fifo"; 113f60ac27eSMatt Spinler } 114f60ac27eSMatt Spinler 1155342d9adSMatt Spinler /** 1165342d9adSMatt Spinler * @brief Destructor 1175342d9adSMatt Spinler */ ~MockHostInterface()118f60ac27eSMatt Spinler virtual ~MockHostInterface() 119f60ac27eSMatt Spinler { 1205342d9adSMatt Spinler std::filesystem::remove_all(_fifo.parent_path()); 121f60ac27eSMatt Spinler } 122f60ac27eSMatt Spinler 123f60ac27eSMatt Spinler MOCK_METHOD(CmdStatus, sendNewLogCmd, (uint32_t, uint32_t), (override)); 124f60ac27eSMatt Spinler 1255342d9adSMatt Spinler /** 1265342d9adSMatt Spinler * @brief Cancels waiting for a command response 1275342d9adSMatt Spinler */ cancelCmd()1285342d9adSMatt Spinler virtual void cancelCmd() override 1295342d9adSMatt Spinler { 1305342d9adSMatt Spinler _inProgress = false; 1315342d9adSMatt Spinler _source = nullptr; 1325342d9adSMatt Spinler } 1335342d9adSMatt Spinler 1345342d9adSMatt Spinler /** 1355342d9adSMatt Spinler * @brief Returns the amount of time to wait before retrying after 1365342d9adSMatt Spinler * a failed send command. 1375342d9adSMatt Spinler * 1385342d9adSMatt Spinler * @return milliseconds - The amount of time to wait 1395342d9adSMatt Spinler */ getSendRetryDelay() const1405342d9adSMatt Spinler virtual std::chrono::milliseconds getSendRetryDelay() const override 1415342d9adSMatt Spinler { 1425342d9adSMatt Spinler return std::chrono::milliseconds(2); 1435342d9adSMatt Spinler } 1445342d9adSMatt Spinler 1455342d9adSMatt Spinler /** 1465342d9adSMatt Spinler * @brief Returns the amount of time to wait before retrying after 1475342d9adSMatt Spinler * a command receive. 1485342d9adSMatt Spinler * 1495342d9adSMatt Spinler * @return milliseconds - The amount of time to wait 1505342d9adSMatt Spinler */ getReceiveRetryDelay() const1515342d9adSMatt Spinler virtual std::chrono::milliseconds getReceiveRetryDelay() const override 1525342d9adSMatt Spinler { 1535342d9adSMatt Spinler return std::chrono::milliseconds(2); 1545342d9adSMatt Spinler } 1555342d9adSMatt Spinler 1565342d9adSMatt Spinler /** 15741293cb8SMatt Spinler * @brief Returns the amount of time to wait before retrying if the 15841293cb8SMatt Spinler * host firmware's PEL storage was full and it can't store 15941293cb8SMatt Spinler * any more logs until it is freed up somehow. 16041293cb8SMatt Spinler * 16141293cb8SMatt Spinler * @return milliseconds - The amount of time to wait 16241293cb8SMatt Spinler */ getHostFullRetryDelay() const16341293cb8SMatt Spinler virtual std::chrono::milliseconds getHostFullRetryDelay() const override 16441293cb8SMatt Spinler { 1656aae6a0cSMatt Spinler return std::chrono::milliseconds(400); 16641293cb8SMatt Spinler } 16741293cb8SMatt Spinler 16841293cb8SMatt Spinler /** 169e5f7508bSMatt Spinler * @brief Returns the amount of time to wait after the host is up 170e5f7508bSMatt Spinler * before sending commands. 171e5f7508bSMatt Spinler * 172e5f7508bSMatt Spinler * @return milliseconds - The amount of time to wait 173e5f7508bSMatt Spinler */ getHostUpDelay() const174e5f7508bSMatt Spinler virtual std::chrono::milliseconds getHostUpDelay() const override 175e5f7508bSMatt Spinler { 176e5f7508bSMatt Spinler return std::chrono::milliseconds(0); 177e5f7508bSMatt Spinler } 178e5f7508bSMatt Spinler 179e5f7508bSMatt Spinler /** 1805342d9adSMatt Spinler * @brief Returns the number of commands processed 1815342d9adSMatt Spinler */ numCmdsProcessed() const1825342d9adSMatt Spinler size_t numCmdsProcessed() const 1835342d9adSMatt Spinler { 1845342d9adSMatt Spinler return _cmdsProcessed; 1855342d9adSMatt Spinler } 1865342d9adSMatt Spinler 1875342d9adSMatt Spinler /** 1885342d9adSMatt Spinler * @brief Writes the data passed in to the FIFO 1895342d9adSMatt Spinler * 1905342d9adSMatt Spinler * @param[in] hostResponse - use a 0 to indicate success 1915342d9adSMatt Spinler * 1925342d9adSMatt Spinler * @return CmdStatus - success or failure 1935342d9adSMatt Spinler */ send(uint8_t hostResponse)1945342d9adSMatt Spinler CmdStatus send(uint8_t hostResponse) 1955342d9adSMatt Spinler { 1965342d9adSMatt Spinler // Create a FIFO once. 1975342d9adSMatt Spinler if (!std::filesystem::exists(_fifo)) 1985342d9adSMatt Spinler { 1995342d9adSMatt Spinler if (mkfifo(_fifo.c_str(), 0622)) 2005342d9adSMatt Spinler { 2015342d9adSMatt Spinler ADD_FAILURE() << "Failed mkfifo " << _fifo << strerror(errno); 2025342d9adSMatt Spinler exit(-1); 2035342d9adSMatt Spinler } 2045342d9adSMatt Spinler } 2055342d9adSMatt Spinler 2065342d9adSMatt Spinler // Open it and register the reponse callback to 2075342d9adSMatt Spinler // be used on FD activity. 2085342d9adSMatt Spinler int fd = open(_fifo.c_str(), O_NONBLOCK | O_RDWR); 2095342d9adSMatt Spinler EXPECT_TRUE(fd >= 0) << "Unable to open FIFO"; 2105342d9adSMatt Spinler 211075c7923SPatrick Williams auto callback = 212075c7923SPatrick Williams [this](sdeventplus::source::IO& source, int fd, uint32_t events) { 2130387a74eSLakshmi Yadlapati this->receive(source, fd, events, nullptr); 2145342d9adSMatt Spinler }; 2155342d9adSMatt Spinler 2165342d9adSMatt Spinler try 2175342d9adSMatt Spinler { 2185342d9adSMatt Spinler _source = std::make_unique<sdeventplus::source::IO>( 2195342d9adSMatt Spinler _event, fd, EPOLLIN, 2205342d9adSMatt Spinler std::bind(callback, std::placeholders::_1, 2215342d9adSMatt Spinler std::placeholders::_2, std::placeholders::_3)); 2225342d9adSMatt Spinler } 22366491c61SPatrick Williams catch (const std::exception& e) 2245342d9adSMatt Spinler { 2255342d9adSMatt Spinler ADD_FAILURE() << "Event exception: " << e.what(); 2265342d9adSMatt Spinler close(fd); 2275342d9adSMatt Spinler return CmdStatus::failure; 2285342d9adSMatt Spinler } 2295342d9adSMatt Spinler 2305342d9adSMatt Spinler // Write the fake host reponse to the FIFO 2315342d9adSMatt Spinler auto bytesWritten = write(fd, &hostResponse, sizeof(hostResponse)); 2325342d9adSMatt Spinler EXPECT_EQ(bytesWritten, sizeof(hostResponse)); 2335342d9adSMatt Spinler 2345342d9adSMatt Spinler _inProgress = true; 2355342d9adSMatt Spinler 2365342d9adSMatt Spinler return CmdStatus::success; 2375342d9adSMatt Spinler } 2385342d9adSMatt Spinler 239f60ac27eSMatt Spinler protected: 2405342d9adSMatt Spinler /** 2415342d9adSMatt Spinler * @brief Reads the data written to the fifo and then calls 2425342d9adSMatt Spinler * the subscriber's callback. 2435342d9adSMatt Spinler * 2445342d9adSMatt Spinler * Nonzero data indicates a command failure (for testing bad path). 2455342d9adSMatt Spinler * 2465342d9adSMatt Spinler * @param[in] source - The event source object 2475342d9adSMatt Spinler * @param[in] fd - The file descriptor used 2485342d9adSMatt Spinler * @param[in] events - The event bits 2495342d9adSMatt Spinler */ receive(sdeventplus::source::IO &,int,uint32_t events,pldm_transport *)250d26fa3e7SPatrick Williams void receive(sdeventplus::source::IO& /*source*/, int /*fd*/, 2510387a74eSLakshmi Yadlapati uint32_t events, pldm_transport* /*transport*/) override 252f60ac27eSMatt Spinler { 2535342d9adSMatt Spinler if (!(events & EPOLLIN)) 2545342d9adSMatt Spinler { 2555342d9adSMatt Spinler return; 2565342d9adSMatt Spinler } 2575342d9adSMatt Spinler 2585342d9adSMatt Spinler _inProgress = false; 2595342d9adSMatt Spinler 2605342d9adSMatt Spinler int newFD = open(_fifo.c_str(), O_NONBLOCK | O_RDONLY); 2615342d9adSMatt Spinler ASSERT_TRUE(newFD >= 0) << "Failed to open FIFO"; 2625342d9adSMatt Spinler 2635342d9adSMatt Spinler // Read the host success/failure response from the FIFO. 2645342d9adSMatt Spinler uint8_t data; 2655342d9adSMatt Spinler auto bytesRead = read(newFD, &data, sizeof(data)); 2665342d9adSMatt Spinler EXPECT_EQ(bytesRead, sizeof(data)); 2675342d9adSMatt Spinler 2685342d9adSMatt Spinler close(newFD); 2695342d9adSMatt Spinler 2705342d9adSMatt Spinler ResponseStatus status = ResponseStatus::success; 2715342d9adSMatt Spinler if (data != 0) 2725342d9adSMatt Spinler { 2735342d9adSMatt Spinler status = ResponseStatus::failure; 2745342d9adSMatt Spinler } 2755342d9adSMatt Spinler 276a44efe48SMatt Spinler callResponseFunc(status); 2775342d9adSMatt Spinler 278f60ac27eSMatt Spinler // Keep account of the number of commands responses for testing. 279f60ac27eSMatt Spinler _cmdsProcessed++; 280f60ac27eSMatt Spinler } 281f60ac27eSMatt Spinler 282f60ac27eSMatt Spinler private: 2835342d9adSMatt Spinler /** 2845342d9adSMatt Spinler * @brief The event source for the fifo 2855342d9adSMatt Spinler */ 2865342d9adSMatt Spinler std::unique_ptr<sdeventplus::source::IO> _source; 2875342d9adSMatt Spinler 2885342d9adSMatt Spinler /** 2895342d9adSMatt Spinler * @brief the path to the fifo 2905342d9adSMatt Spinler */ 2915342d9adSMatt Spinler std::filesystem::path _fifo; 2925342d9adSMatt Spinler 2935342d9adSMatt Spinler /** 2945342d9adSMatt Spinler * @brief The number of commands processed 2955342d9adSMatt Spinler */ 296f60ac27eSMatt Spinler size_t _cmdsProcessed = 0; 29709d6400fSMatt Spinler }; 29809d6400fSMatt Spinler 299d96fa60dSMatt Spinler class MockJournal : public JournalBase 300d96fa60dSMatt Spinler { 301d96fa60dSMatt Spinler public: MockJournal()302d96fa60dSMatt Spinler MockJournal() {} 303d96fa60dSMatt Spinler 304d96fa60dSMatt Spinler MOCK_METHOD(std::vector<std::string>, getMessages, 305d96fa60dSMatt Spinler (const std::string&, size_t), (const override)); 3069d921096SMatt Spinler 3079d921096SMatt Spinler MOCK_METHOD(void, sync, (), (const override)); 308d96fa60dSMatt Spinler }; 309d96fa60dSMatt Spinler 31009d6400fSMatt Spinler } // namespace pels 31109d6400fSMatt Spinler } // namespace openpower 312