blob: 510974c302bfe54c63928a6ddca61099a4ca55ae [file] [log] [blame]
Matt Spinler09d64002019-09-11 14:29:46 -05001#include "extensions/openpower-pels/data_interface.hpp"
Matt Spinlerf60ac272019-12-11 13:47:50 -06002#include "extensions/openpower-pels/host_interface.hpp"
3
4#include <fcntl.h>
5
6#include <filesystem>
7#include <sdeventplus/source/io.hpp>
Matt Spinler09d64002019-09-11 14:29:46 -05008
9#include <gmock/gmock.h>
10
11namespace openpower
12{
13namespace pels
14{
15
16class MockDataInterface : public DataInterfaceBase
17{
18 public:
19 MockDataInterface()
20 {
21 }
Matt Spinlerf60ac272019-12-11 13:47:50 -060022 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));
Matt Spinler677381b2020-01-23 10:04:29 -060026 MOCK_METHOD(std::string, getBMCFWVersionID, (), (const override));
Matt Spinler24a85582020-01-27 16:40:21 -060027 MOCK_METHOD(bool, getHostPELEnablement, (), (const override));
Matt Spinler4aa23a12020-02-03 15:05:09 -060028 MOCK_METHOD(std::string, getBMCState, (), (const override));
29 MOCK_METHOD(std::string, getChassisState, (), (const override));
30 MOCK_METHOD(std::string, getHostState, (), (const override));
Matt Spinler075e5ba2020-02-21 15:46:00 -060031 MOCK_METHOD(std::string, getMotherboardCCIN, (), (const override));
Matt Spinler60c4e792020-03-13 13:45:36 -050032 MOCK_METHOD(void, getHWCalloutFields,
Matt Spinler9b90e2a2020-04-14 10:59:04 -050033 (const std::string&, std::string&, std::string&, std::string&),
Matt Spinler60c4e792020-03-13 13:45:36 -050034 (const override));
Matt Spinler9b90e2a2020-04-14 10:59:04 -050035 MOCK_METHOD(std::string, getLocationCode, (const std::string&),
36 (const override));
Matt Spinler1ab66962020-10-29 13:21:44 -050037 MOCK_METHOD(std::vector<std::string>, getSystemNames, (), (const override));
Matt Spinler5fb24c12020-06-04 11:21:33 -050038 MOCK_METHOD(std::string, expandLocationCode, (const std::string&, uint16_t),
39 (const override));
40 MOCK_METHOD(std::string, getInventoryFromLocCode,
Matt Spinler2f9225a2020-08-05 12:58:49 -050041 (const std::string&, uint16_t, bool), (const override));
Matt Spinlerf60ac272019-12-11 13:47:50 -060042
Matt Spinler34a904c2020-08-05 14:53:28 -050043 MOCK_METHOD(std::string, getFaultLEDGroup, (const std::string&),
44 (const override));
45
46 MOCK_METHOD(void, assertLEDGroup, (const std::string&, bool),
47 (const override));
48
Matt Spinlerf60ac272019-12-11 13:47:50 -060049 void changeHostState(bool newState)
50 {
Matt Spinler4aa23a12020-02-03 15:05:09 -060051 setHostUp(newState);
Matt Spinlerf60ac272019-12-11 13:47:50 -060052 }
53
54 void setHMCManaged(bool managed)
55 {
56 _hmcManaged = managed;
57 }
58};
59
60/**
61 * @brief The mock HostInterface class
Matt Spinler5342d9a2019-12-12 11:03:39 -060062 *
63 * This replaces the PLDM calls with a FIFO for the asynchronous
64 * responses.
Matt Spinlerf60ac272019-12-11 13:47:50 -060065 */
66class MockHostInterface : public HostInterface
67{
68 public:
Matt Spinler5342d9a2019-12-12 11:03:39 -060069 /**
70 * @brief Constructor
71 *
72 * @param[in] event - The sd_event object
73 * @param[in] dataIface - The DataInterface class
74 */
Matt Spinlerf60ac272019-12-11 13:47:50 -060075 MockHostInterface(sd_event* event, DataInterfaceBase& dataIface) :
76 HostInterface(event, dataIface)
77 {
Matt Spinler5342d9a2019-12-12 11:03:39 -060078 char templ[] = "/tmp/cmdfifoXXXXXX";
79 std::filesystem::path dir = mkdtemp(templ);
80 _fifo = dir / "fifo";
Matt Spinlerf60ac272019-12-11 13:47:50 -060081 }
82
Matt Spinler5342d9a2019-12-12 11:03:39 -060083 /**
84 * @brief Destructor
85 */
Matt Spinlerf60ac272019-12-11 13:47:50 -060086 virtual ~MockHostInterface()
87 {
Matt Spinler5342d9a2019-12-12 11:03:39 -060088 std::filesystem::remove_all(_fifo.parent_path());
Matt Spinlerf60ac272019-12-11 13:47:50 -060089 }
90
91 MOCK_METHOD(CmdStatus, sendNewLogCmd, (uint32_t, uint32_t), (override));
92
Matt Spinler5342d9a2019-12-12 11:03:39 -060093 /**
94 * @brief Cancels waiting for a command response
95 */
96 virtual void cancelCmd() override
97 {
98 _inProgress = false;
99 _source = nullptr;
100 }
101
102 /**
103 * @brief Returns the amount of time to wait before retrying after
104 * a failed send command.
105 *
106 * @return milliseconds - The amount of time to wait
107 */
108 virtual std::chrono::milliseconds getSendRetryDelay() const override
109 {
110 return std::chrono::milliseconds(2);
111 }
112
113 /**
114 * @brief Returns the amount of time to wait before retrying after
115 * a command receive.
116 *
117 * @return milliseconds - The amount of time to wait
118 */
119 virtual std::chrono::milliseconds getReceiveRetryDelay() const override
120 {
121 return std::chrono::milliseconds(2);
122 }
123
124 /**
Matt Spinler41293cb2019-12-12 13:11:09 -0600125 * @brief Returns the amount of time to wait before retrying if the
126 * host firmware's PEL storage was full and it can't store
127 * any more logs until it is freed up somehow.
128 *
129 * @return milliseconds - The amount of time to wait
130 */
131 virtual std::chrono::milliseconds getHostFullRetryDelay() const override
132 {
Matt Spinler6aae6a02020-02-07 12:46:07 -0600133 return std::chrono::milliseconds(400);
Matt Spinler41293cb2019-12-12 13:11:09 -0600134 }
135
136 /**
Matt Spinler5342d9a2019-12-12 11:03:39 -0600137 * @brief Returns the number of commands processed
138 */
139 size_t numCmdsProcessed() const
140 {
141 return _cmdsProcessed;
142 }
143
144 /**
145 * @brief Writes the data passed in to the FIFO
146 *
147 * @param[in] hostResponse - use a 0 to indicate success
148 *
149 * @return CmdStatus - success or failure
150 */
151 CmdStatus send(uint8_t hostResponse)
152 {
153 // Create a FIFO once.
154 if (!std::filesystem::exists(_fifo))
155 {
156 if (mkfifo(_fifo.c_str(), 0622))
157 {
158 ADD_FAILURE() << "Failed mkfifo " << _fifo << strerror(errno);
159 exit(-1);
160 }
161 }
162
163 // Open it and register the reponse callback to
164 // be used on FD activity.
165 int fd = open(_fifo.c_str(), O_NONBLOCK | O_RDWR);
166 EXPECT_TRUE(fd >= 0) << "Unable to open FIFO";
167
168 auto callback = [this](sdeventplus::source::IO& source, int fd,
169 uint32_t events) {
170 this->receive(source, fd, events);
171 };
172
173 try
174 {
175 _source = std::make_unique<sdeventplus::source::IO>(
176 _event, fd, EPOLLIN,
177 std::bind(callback, std::placeholders::_1,
178 std::placeholders::_2, std::placeholders::_3));
179 }
180 catch (std::exception& e)
181 {
182 ADD_FAILURE() << "Event exception: " << e.what();
183 close(fd);
184 return CmdStatus::failure;
185 }
186
187 // Write the fake host reponse to the FIFO
188 auto bytesWritten = write(fd, &hostResponse, sizeof(hostResponse));
189 EXPECT_EQ(bytesWritten, sizeof(hostResponse));
190
191 _inProgress = true;
192
193 return CmdStatus::success;
194 }
195
Matt Spinlerf60ac272019-12-11 13:47:50 -0600196 protected:
Matt Spinler5342d9a2019-12-12 11:03:39 -0600197 /**
198 * @brief Reads the data written to the fifo and then calls
199 * the subscriber's callback.
200 *
201 * Nonzero data indicates a command failure (for testing bad path).
202 *
203 * @param[in] source - The event source object
204 * @param[in] fd - The file descriptor used
205 * @param[in] events - The event bits
206 */
Matt Spinlerf60ac272019-12-11 13:47:50 -0600207 void receive(sdeventplus::source::IO& source, int fd,
208 uint32_t events) override
209 {
Matt Spinler5342d9a2019-12-12 11:03:39 -0600210 if (!(events & EPOLLIN))
211 {
212 return;
213 }
214
215 _inProgress = false;
216
217 int newFD = open(_fifo.c_str(), O_NONBLOCK | O_RDONLY);
218 ASSERT_TRUE(newFD >= 0) << "Failed to open FIFO";
219
220 // Read the host success/failure response from the FIFO.
221 uint8_t data;
222 auto bytesRead = read(newFD, &data, sizeof(data));
223 EXPECT_EQ(bytesRead, sizeof(data));
224
225 close(newFD);
226
227 ResponseStatus status = ResponseStatus::success;
228 if (data != 0)
229 {
230 status = ResponseStatus::failure;
231 }
232
Matt Spinlera44efe42020-03-03 10:30:16 -0600233 callResponseFunc(status);
Matt Spinler5342d9a2019-12-12 11:03:39 -0600234
Matt Spinlerf60ac272019-12-11 13:47:50 -0600235 // Keep account of the number of commands responses for testing.
236 _cmdsProcessed++;
237 }
238
239 private:
Matt Spinler5342d9a2019-12-12 11:03:39 -0600240 /**
241 * @brief The event source for the fifo
242 */
243 std::unique_ptr<sdeventplus::source::IO> _source;
244
245 /**
246 * @brief the path to the fifo
247 */
248 std::filesystem::path _fifo;
249
250 /**
251 * @brief The number of commands processed
252 */
Matt Spinlerf60ac272019-12-11 13:47:50 -0600253 size_t _cmdsProcessed = 0;
Matt Spinler09d64002019-09-11 14:29:46 -0500254};
255
256} // namespace pels
257} // namespace openpower