blob: ef003971754880d22a209c06874c7603f1882bda [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
Matt Spinlerf60ac272019-12-11 13:47:50 -06006#include <sdeventplus/source/io.hpp>
Matt Spinler09d64002019-09-11 14:29:46 -05007
Patrick Williams2544b412022-10-04 08:41:06 -05008#include <filesystem>
9
Matt Spinler09d64002019-09-11 14:29:46 -050010#include <gmock/gmock.h>
11
12namespace openpower
13{
14namespace pels
15{
16
17class MockDataInterface : public DataInterfaceBase
18{
19 public:
Patrick Williams2544b412022-10-04 08:41:06 -050020 MockDataInterface() {}
Matt Spinlerf60ac272019-12-11 13:47:50 -060021 MOCK_METHOD(std::string, getMachineTypeModel, (), (const override));
22 MOCK_METHOD(std::string, getMachineSerialNumber, (), (const override));
23 MOCK_METHOD(std::string, getServerFWVersion, (), (const override));
24 MOCK_METHOD(std::string, getBMCFWVersion, (), (const override));
Matt Spinler677381b2020-01-23 10:04:29 -060025 MOCK_METHOD(std::string, getBMCFWVersionID, (), (const override));
Matt Spinler24a85582020-01-27 16:40:21 -060026 MOCK_METHOD(bool, getHostPELEnablement, (), (const override));
Matt Spinler4aa23a12020-02-03 15:05:09 -060027 MOCK_METHOD(std::string, getBMCState, (), (const override));
28 MOCK_METHOD(std::string, getChassisState, (), (const override));
29 MOCK_METHOD(std::string, getHostState, (), (const override));
Matt Spinler075e5ba2020-02-21 15:46:00 -060030 MOCK_METHOD(std::string, getMotherboardCCIN, (), (const override));
Matt Spinler60c4e792020-03-13 13:45:36 -050031 MOCK_METHOD(void, getHWCalloutFields,
Matt Spinler9b90e2a2020-04-14 10:59:04 -050032 (const std::string&, std::string&, std::string&, std::string&),
Matt Spinler60c4e792020-03-13 13:45:36 -050033 (const override));
Matt Spinler9b90e2a2020-04-14 10:59:04 -050034 MOCK_METHOD(std::string, getLocationCode, (const std::string&),
35 (const override));
Matt Spinler1ab66962020-10-29 13:21:44 -050036 MOCK_METHOD(std::vector<std::string>, getSystemNames, (), (const override));
Matt Spinler5fb24c12020-06-04 11:21:33 -050037 MOCK_METHOD(std::string, expandLocationCode, (const std::string&, uint16_t),
38 (const override));
39 MOCK_METHOD(std::string, getInventoryFromLocCode,
Matt Spinler2f9225a2020-08-05 12:58:49 -050040 (const std::string&, uint16_t, bool), (const override));
Matt Spinler34a904c2020-08-05 14:53:28 -050041 MOCK_METHOD(void, assertLEDGroup, (const std::string&, bool),
42 (const override));
Matt Spinler993168d2021-04-07 16:05:03 -050043 MOCK_METHOD(void, setFunctional, (const std::string&, bool),
44 (const override));
Ben Tynere32b7e72021-05-18 12:38:40 -050045 MOCK_METHOD(std::vector<uint8_t>, getSystemIMKeyword, (), (const override));
Sumit Kumar3b8ed7f2021-05-18 12:38:35 -050046 MOCK_METHOD(bool, getQuiesceOnError, (), (const override));
Sumit Kumar76198a22021-07-15 05:59:57 -050047 MOCK_METHOD(void, setCriticalAssociation, (const std::string&),
48 (const override));
Sumit Kumar9d43a722021-08-24 09:46:19 -050049 MOCK_METHOD(std::vector<bool>, checkDumpStatus,
50 (const std::vector<std::string>&), (const override));
Sumit Kumar2c36fdd2021-09-21 03:12:11 -050051 MOCK_METHOD(std::string, getBootState, (), (const override));
Jayanth Othayothecaa2fc2021-11-05 02:02:52 -050052 MOCK_METHOD(void, createGuardRecord,
53 (const std::vector<uint8_t>&, const std::string&,
54 const std::string&),
55 (const override));
Sumit Kumar3e274432021-09-14 06:37:56 -050056 MOCK_METHOD(void, createProgressSRC,
57 (const uint64_t&, const std::vector<uint8_t>&),
58 (const override));
Sumit Kumar027bf282022-01-24 11:25:19 -060059 MOCK_METHOD(std::vector<uint32_t>, getLogIDWithHwIsolation, (),
60 (const override));
Matt Spinler34a904c2020-08-05 14:53:28 -050061
Matt Spinlerf60ac272019-12-11 13:47:50 -060062 void changeHostState(bool newState)
63 {
Matt Spinler4aa23a12020-02-03 15:05:09 -060064 setHostUp(newState);
Matt Spinlerf60ac272019-12-11 13:47:50 -060065 }
66
67 void setHMCManaged(bool managed)
68 {
69 _hmcManaged = managed;
70 }
71};
72
73/**
74 * @brief The mock HostInterface class
Matt Spinler5342d9a2019-12-12 11:03:39 -060075 *
76 * This replaces the PLDM calls with a FIFO for the asynchronous
77 * responses.
Matt Spinlerf60ac272019-12-11 13:47:50 -060078 */
79class MockHostInterface : public HostInterface
80{
81 public:
Matt Spinler5342d9a2019-12-12 11:03:39 -060082 /**
83 * @brief Constructor
84 *
85 * @param[in] event - The sd_event object
86 * @param[in] dataIface - The DataInterface class
87 */
Matt Spinlerf60ac272019-12-11 13:47:50 -060088 MockHostInterface(sd_event* event, DataInterfaceBase& dataIface) :
89 HostInterface(event, dataIface)
90 {
Matt Spinler5342d9a2019-12-12 11:03:39 -060091 char templ[] = "/tmp/cmdfifoXXXXXX";
92 std::filesystem::path dir = mkdtemp(templ);
93 _fifo = dir / "fifo";
Matt Spinlerf60ac272019-12-11 13:47:50 -060094 }
95
Matt Spinler5342d9a2019-12-12 11:03:39 -060096 /**
97 * @brief Destructor
98 */
Matt Spinlerf60ac272019-12-11 13:47:50 -060099 virtual ~MockHostInterface()
100 {
Matt Spinler5342d9a2019-12-12 11:03:39 -0600101 std::filesystem::remove_all(_fifo.parent_path());
Matt Spinlerf60ac272019-12-11 13:47:50 -0600102 }
103
104 MOCK_METHOD(CmdStatus, sendNewLogCmd, (uint32_t, uint32_t), (override));
105
Matt Spinler5342d9a2019-12-12 11:03:39 -0600106 /**
107 * @brief Cancels waiting for a command response
108 */
109 virtual void cancelCmd() override
110 {
111 _inProgress = false;
112 _source = nullptr;
113 }
114
115 /**
116 * @brief Returns the amount of time to wait before retrying after
117 * a failed send command.
118 *
119 * @return milliseconds - The amount of time to wait
120 */
121 virtual std::chrono::milliseconds getSendRetryDelay() const override
122 {
123 return std::chrono::milliseconds(2);
124 }
125
126 /**
127 * @brief Returns the amount of time to wait before retrying after
128 * a command receive.
129 *
130 * @return milliseconds - The amount of time to wait
131 */
132 virtual std::chrono::milliseconds getReceiveRetryDelay() const override
133 {
134 return std::chrono::milliseconds(2);
135 }
136
137 /**
Matt Spinler41293cb2019-12-12 13:11:09 -0600138 * @brief Returns the amount of time to wait before retrying if the
139 * host firmware's PEL storage was full and it can't store
140 * any more logs until it is freed up somehow.
141 *
142 * @return milliseconds - The amount of time to wait
143 */
144 virtual std::chrono::milliseconds getHostFullRetryDelay() const override
145 {
Matt Spinler6aae6a02020-02-07 12:46:07 -0600146 return std::chrono::milliseconds(400);
Matt Spinler41293cb2019-12-12 13:11:09 -0600147 }
148
149 /**
Matt Spinlere5f75082022-01-24 16:09:51 -0600150 * @brief Returns the amount of time to wait after the host is up
151 * before sending commands.
152 *
153 * @return milliseconds - The amount of time to wait
154 */
155 virtual std::chrono::milliseconds getHostUpDelay() const override
156 {
157 return std::chrono::milliseconds(0);
158 }
159
160 /**
Matt Spinler5342d9a2019-12-12 11:03:39 -0600161 * @brief Returns the number of commands processed
162 */
163 size_t numCmdsProcessed() const
164 {
165 return _cmdsProcessed;
166 }
167
168 /**
169 * @brief Writes the data passed in to the FIFO
170 *
171 * @param[in] hostResponse - use a 0 to indicate success
172 *
173 * @return CmdStatus - success or failure
174 */
175 CmdStatus send(uint8_t hostResponse)
176 {
177 // Create a FIFO once.
178 if (!std::filesystem::exists(_fifo))
179 {
180 if (mkfifo(_fifo.c_str(), 0622))
181 {
182 ADD_FAILURE() << "Failed mkfifo " << _fifo << strerror(errno);
183 exit(-1);
184 }
185 }
186
187 // Open it and register the reponse callback to
188 // be used on FD activity.
189 int fd = open(_fifo.c_str(), O_NONBLOCK | O_RDWR);
190 EXPECT_TRUE(fd >= 0) << "Unable to open FIFO";
191
192 auto callback = [this](sdeventplus::source::IO& source, int fd,
193 uint32_t events) {
194 this->receive(source, fd, events);
195 };
196
197 try
198 {
199 _source = std::make_unique<sdeventplus::source::IO>(
200 _event, fd, EPOLLIN,
201 std::bind(callback, std::placeholders::_1,
202 std::placeholders::_2, std::placeholders::_3));
203 }
Patrick Williams66491c62021-10-06 12:23:37 -0500204 catch (const std::exception& e)
Matt Spinler5342d9a2019-12-12 11:03:39 -0600205 {
206 ADD_FAILURE() << "Event exception: " << e.what();
207 close(fd);
208 return CmdStatus::failure;
209 }
210
211 // Write the fake host reponse to the FIFO
212 auto bytesWritten = write(fd, &hostResponse, sizeof(hostResponse));
213 EXPECT_EQ(bytesWritten, sizeof(hostResponse));
214
215 _inProgress = true;
216
217 return CmdStatus::success;
218 }
219
Matt Spinlerf60ac272019-12-11 13:47:50 -0600220 protected:
Matt Spinler5342d9a2019-12-12 11:03:39 -0600221 /**
222 * @brief Reads the data written to the fifo and then calls
223 * the subscriber's callback.
224 *
225 * Nonzero data indicates a command failure (for testing bad path).
226 *
227 * @param[in] source - The event source object
228 * @param[in] fd - The file descriptor used
229 * @param[in] events - The event bits
230 */
Patrick Williamsd26fa3e2021-04-21 15:22:23 -0500231 void receive(sdeventplus::source::IO& /*source*/, int /*fd*/,
Matt Spinlerf60ac272019-12-11 13:47:50 -0600232 uint32_t events) override
233 {
Matt Spinler5342d9a2019-12-12 11:03:39 -0600234 if (!(events & EPOLLIN))
235 {
236 return;
237 }
238
239 _inProgress = false;
240
241 int newFD = open(_fifo.c_str(), O_NONBLOCK | O_RDONLY);
242 ASSERT_TRUE(newFD >= 0) << "Failed to open FIFO";
243
244 // Read the host success/failure response from the FIFO.
245 uint8_t data;
246 auto bytesRead = read(newFD, &data, sizeof(data));
247 EXPECT_EQ(bytesRead, sizeof(data));
248
249 close(newFD);
250
251 ResponseStatus status = ResponseStatus::success;
252 if (data != 0)
253 {
254 status = ResponseStatus::failure;
255 }
256
Matt Spinlera44efe42020-03-03 10:30:16 -0600257 callResponseFunc(status);
Matt Spinler5342d9a2019-12-12 11:03:39 -0600258
Matt Spinlerf60ac272019-12-11 13:47:50 -0600259 // Keep account of the number of commands responses for testing.
260 _cmdsProcessed++;
261 }
262
263 private:
Matt Spinler5342d9a2019-12-12 11:03:39 -0600264 /**
265 * @brief The event source for the fifo
266 */
267 std::unique_ptr<sdeventplus::source::IO> _source;
268
269 /**
270 * @brief the path to the fifo
271 */
272 std::filesystem::path _fifo;
273
274 /**
275 * @brief The number of commands processed
276 */
Matt Spinlerf60ac272019-12-11 13:47:50 -0600277 size_t _cmdsProcessed = 0;
Matt Spinler09d64002019-09-11 14:29:46 -0500278};
279
280} // namespace pels
281} // namespace openpower