diff options
author | Matt Spinler <spinler@us.ibm.com> | 2019-12-12 11:03:39 -0600 |
---|---|---|
committer | Matt Spinler <spinler@us.ibm.com> | 2020-01-27 08:06:26 -0600 |
commit | 5342d9ad13453e2fe9558b12137cd9be2e220544 (patch) | |
tree | 5ee6760c188aea8d84f4f6b4d1fe89a6b512a0ae | |
parent | f77debb9afbbe007ed7e2c3f79ddeb6f1b6f7c49 (diff) | |
download | phosphor-logging-5342d9ad13453e2fe9558b12137cd9be2e220544.tar.gz phosphor-logging-5342d9ad13453e2fe9558b12137cd9be2e220544.zip |
PEL: Mock the new PEL available cmd
Instead of using PLDM, just write to a FIFO in the filesystem where what
is written can be asynchronously read back from an event callback just
like how PLDM commands behave.
There is just a single byte written to the FIFO - a zero if the
command is considered successful, something nonzero to indicate
it should be a failure.
Change-Id: I1fd79782126a6b1555597a4642b9ca3bfd030a79
-rw-r--r-- | test/openpower-pels/mocks.hpp | 156 |
1 files changed, 155 insertions, 1 deletions
diff --git a/test/openpower-pels/mocks.hpp b/test/openpower-pels/mocks.hpp index c2a84a0..dcce142 100644 --- a/test/openpower-pels/mocks.hpp +++ b/test/openpower-pels/mocks.hpp @@ -37,34 +37,188 @@ class MockDataInterface : public DataInterfaceBase /** * @brief The mock HostInterface class + * + * This replaces the PLDM calls with a FIFO for the asynchronous + * responses. */ class MockHostInterface : public HostInterface { public: + /** + * @brief Constructor + * + * @param[in] event - The sd_event object + * @param[in] dataIface - The DataInterface class + */ MockHostInterface(sd_event* event, DataInterfaceBase& dataIface) : HostInterface(event, dataIface) { + char templ[] = "/tmp/cmdfifoXXXXXX"; + std::filesystem::path dir = mkdtemp(templ); + _fifo = dir / "fifo"; } + /** + * @brief Destructor + */ virtual ~MockHostInterface() { + std::filesystem::remove_all(_fifo.parent_path()); } + MOCK_METHOD(CmdStatus, sendNewLogCmd, (uint32_t, uint32_t), (override)); + + /** + * @brief Cancels waiting for a command response + */ virtual void cancelCmd() override { + _inProgress = false; + _source = nullptr; } - MOCK_METHOD(CmdStatus, sendNewLogCmd, (uint32_t, uint32_t), (override)); + /** + * @brief Returns the amount of time to wait before retrying after + * a failed send command. + * + * @return milliseconds - The amount of time to wait + */ + virtual std::chrono::milliseconds getSendRetryDelay() const override + { + return std::chrono::milliseconds(2); + } + + /** + * @brief Returns the amount of time to wait before retrying after + * a command receive. + * + * @return milliseconds - The amount of time to wait + */ + virtual std::chrono::milliseconds getReceiveRetryDelay() const override + { + return std::chrono::milliseconds(2); + } + + /** + * @brief Returns the number of commands processed + */ + size_t numCmdsProcessed() const + { + return _cmdsProcessed; + } + + /** + * @brief Writes the data passed in to the FIFO + * + * @param[in] hostResponse - use a 0 to indicate success + * + * @return CmdStatus - success or failure + */ + CmdStatus send(uint8_t hostResponse) + { + // Create a FIFO once. + if (!std::filesystem::exists(_fifo)) + { + if (mkfifo(_fifo.c_str(), 0622)) + { + ADD_FAILURE() << "Failed mkfifo " << _fifo << strerror(errno); + exit(-1); + } + } + + // Open it and register the reponse callback to + // be used on FD activity. + int fd = open(_fifo.c_str(), O_NONBLOCK | O_RDWR); + EXPECT_TRUE(fd >= 0) << "Unable to open FIFO"; + + auto callback = [this](sdeventplus::source::IO& source, int fd, + uint32_t events) { + this->receive(source, fd, events); + }; + + try + { + _source = std::make_unique<sdeventplus::source::IO>( + _event, fd, EPOLLIN, + std::bind(callback, std::placeholders::_1, + std::placeholders::_2, std::placeholders::_3)); + } + catch (std::exception& e) + { + ADD_FAILURE() << "Event exception: " << e.what(); + close(fd); + return CmdStatus::failure; + } + + // Write the fake host reponse to the FIFO + auto bytesWritten = write(fd, &hostResponse, sizeof(hostResponse)); + EXPECT_EQ(bytesWritten, sizeof(hostResponse)); + + _inProgress = true; + + return CmdStatus::success; + } protected: + /** + * @brief Reads the data written to the fifo and then calls + * the subscriber's callback. + * + * Nonzero data indicates a command failure (for testing bad path). + * + * @param[in] source - The event source object + * @param[in] fd - The file descriptor used + * @param[in] events - The event bits + */ void receive(sdeventplus::source::IO& source, int fd, uint32_t events) override { + if (!(events & EPOLLIN)) + { + return; + } + + _inProgress = false; + + int newFD = open(_fifo.c_str(), O_NONBLOCK | O_RDONLY); + ASSERT_TRUE(newFD >= 0) << "Failed to open FIFO"; + + // Read the host success/failure response from the FIFO. + uint8_t data; + auto bytesRead = read(newFD, &data, sizeof(data)); + EXPECT_EQ(bytesRead, sizeof(data)); + + close(newFD); + + ResponseStatus status = ResponseStatus::success; + if (data != 0) + { + status = ResponseStatus::failure; + } + + if (_responseFunc) + { + (*_responseFunc)(status); + } + // Keep account of the number of commands responses for testing. _cmdsProcessed++; } private: + /** + * @brief The event source for the fifo + */ + std::unique_ptr<sdeventplus::source::IO> _source; + + /** + * @brief the path to the fifo + */ + std::filesystem::path _fifo; + + /** + * @brief The number of commands processed + */ size_t _cmdsProcessed = 0; }; |