blob: 094c6708d7b400912bda582488d83e2d610b001f [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"
Matt Spinlerd96fa602022-12-15 11:11:26 -06003#include "extensions/openpower-pels/journal.hpp"
Matt Spinlerf60ac272019-12-11 13:47:50 -06004
5#include <fcntl.h>
6
Matt Spinlerf60ac272019-12-11 13:47:50 -06007#include <sdeventplus/source/io.hpp>
Matt Spinler09d64002019-09-11 14:29:46 -05008
Patrick Williams2544b412022-10-04 08:41:06 -05009#include <filesystem>
10
Matt Spinler09d64002019-09-11 14:29:46 -050011#include <gmock/gmock.h>
12
13namespace openpower
14{
15namespace pels
16{
17
18class MockDataInterface : public DataInterfaceBase
19{
20 public:
Patrick Williams2544b412022-10-04 08:41:06 -050021 MockDataInterface() {}
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));
Matt Spinlerbad056b2023-01-25 14:16:57 -060040 MOCK_METHOD(std::vector<std::string>, getInventoryFromLocCode,
Matt Spinler2f9225a2020-08-05 12:58:49 -050041 (const std::string&, uint16_t, bool), (const override));
Matt Spinler34a904c2020-08-05 14:53:28 -050042 MOCK_METHOD(void, assertLEDGroup, (const std::string&, bool),
43 (const override));
Matt Spinler993168d2021-04-07 16:05:03 -050044 MOCK_METHOD(void, setFunctional, (const std::string&, bool),
45 (const override));
Ben Tynere32b7e72021-05-18 12:38:40 -050046 MOCK_METHOD(std::vector<uint8_t>, getSystemIMKeyword, (), (const override));
Sumit Kumar3b8ed7f2021-05-18 12:38:35 -050047 MOCK_METHOD(bool, getQuiesceOnError, (), (const override));
Sumit Kumar76198a22021-07-15 05:59:57 -050048 MOCK_METHOD(void, setCriticalAssociation, (const std::string&),
49 (const override));
Sumit Kumar9d43a722021-08-24 09:46:19 -050050 MOCK_METHOD(std::vector<bool>, checkDumpStatus,
51 (const std::vector<std::string>&), (const override));
Sumit Kumar2c36fdd2021-09-21 03:12:11 -050052 MOCK_METHOD(std::string, getBootState, (), (const override));
Jayanth Othayothecaa2fc2021-11-05 02:02:52 -050053 MOCK_METHOD(void, createGuardRecord,
54 (const std::vector<uint8_t>&, const std::string&,
55 const std::string&),
56 (const override));
Sumit Kumar3e274432021-09-14 06:37:56 -050057 MOCK_METHOD(void, createProgressSRC,
58 (const uint64_t&, const std::vector<uint8_t>&),
59 (const override));
Sumit Kumar027bf282022-01-24 11:25:19 -060060 MOCK_METHOD(std::vector<uint32_t>, getLogIDWithHwIsolation, (),
61 (const override));
Vijay Lobo875b6c72021-10-20 17:38:56 -050062 MOCK_METHOD(std::vector<uint8_t>, getRawProgressSRC, (), (const override));
Matt Spinler34a904c2020-08-05 14:53:28 -050063
Matt Spinlerf60ac272019-12-11 13:47:50 -060064 void changeHostState(bool newState)
65 {
Matt Spinler4aa23a12020-02-03 15:05:09 -060066 setHostUp(newState);
Matt Spinlerf60ac272019-12-11 13:47:50 -060067 }
68
69 void setHMCManaged(bool managed)
70 {
71 _hmcManaged = managed;
72 }
73};
74
75/**
76 * @brief The mock HostInterface class
Matt Spinler5342d9a2019-12-12 11:03:39 -060077 *
78 * This replaces the PLDM calls with a FIFO for the asynchronous
79 * responses.
Matt Spinlerf60ac272019-12-11 13:47:50 -060080 */
81class MockHostInterface : public HostInterface
82{
83 public:
Matt Spinler5342d9a2019-12-12 11:03:39 -060084 /**
85 * @brief Constructor
86 *
87 * @param[in] event - The sd_event object
88 * @param[in] dataIface - The DataInterface class
89 */
Matt Spinlerf60ac272019-12-11 13:47:50 -060090 MockHostInterface(sd_event* event, DataInterfaceBase& dataIface) :
91 HostInterface(event, dataIface)
92 {
Matt Spinler5342d9a2019-12-12 11:03:39 -060093 char templ[] = "/tmp/cmdfifoXXXXXX";
94 std::filesystem::path dir = mkdtemp(templ);
95 _fifo = dir / "fifo";
Matt Spinlerf60ac272019-12-11 13:47:50 -060096 }
97
Matt Spinler5342d9a2019-12-12 11:03:39 -060098 /**
99 * @brief Destructor
100 */
Matt Spinlerf60ac272019-12-11 13:47:50 -0600101 virtual ~MockHostInterface()
102 {
Matt Spinler5342d9a2019-12-12 11:03:39 -0600103 std::filesystem::remove_all(_fifo.parent_path());
Matt Spinlerf60ac272019-12-11 13:47:50 -0600104 }
105
106 MOCK_METHOD(CmdStatus, sendNewLogCmd, (uint32_t, uint32_t), (override));
107
Matt Spinler5342d9a2019-12-12 11:03:39 -0600108 /**
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 /**
Matt Spinler41293cb2019-12-12 13:11:09 -0600140 * @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 {
Matt Spinler6aae6a02020-02-07 12:46:07 -0600148 return std::chrono::milliseconds(400);
Matt Spinler41293cb2019-12-12 13:11:09 -0600149 }
150
151 /**
Matt Spinlere5f75082022-01-24 16:09:51 -0600152 * @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 /**
Matt Spinler5342d9a2019-12-12 11:03:39 -0600163 * @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
Patrick Williamsac1ba3f2023-05-10 07:50:16 -0500194 auto callback =
195 [this](sdeventplus::source::IO& source, int fd, uint32_t events) {
Matt Spinler5342d9a2019-12-12 11:03:39 -0600196 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 }
Patrick Williams66491c62021-10-06 12:23:37 -0500206 catch (const std::exception& e)
Matt Spinler5342d9a2019-12-12 11:03:39 -0600207 {
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
Matt Spinlerf60ac272019-12-11 13:47:50 -0600222 protected:
Matt Spinler5342d9a2019-12-12 11:03:39 -0600223 /**
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 */
Patrick Williamsd26fa3e2021-04-21 15:22:23 -0500233 void receive(sdeventplus::source::IO& /*source*/, int /*fd*/,
Matt Spinlerf60ac272019-12-11 13:47:50 -0600234 uint32_t events) override
235 {
Matt Spinler5342d9a2019-12-12 11:03:39 -0600236 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
Matt Spinlera44efe42020-03-03 10:30:16 -0600259 callResponseFunc(status);
Matt Spinler5342d9a2019-12-12 11:03:39 -0600260
Matt Spinlerf60ac272019-12-11 13:47:50 -0600261 // Keep account of the number of commands responses for testing.
262 _cmdsProcessed++;
263 }
264
265 private:
Matt Spinler5342d9a2019-12-12 11:03:39 -0600266 /**
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 */
Matt Spinlerf60ac272019-12-11 13:47:50 -0600279 size_t _cmdsProcessed = 0;
Matt Spinler09d64002019-09-11 14:29:46 -0500280};
281
Matt Spinlerd96fa602022-12-15 11:11:26 -0600282class 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));
Matt Spinler9d921092022-12-15 11:54:49 -0600289
290 MOCK_METHOD(void, sync, (), (const override));
Matt Spinlerd96fa602022-12-15 11:11:26 -0600291};
292
Matt Spinler09d64002019-09-11 14:29:46 -0500293} // namespace pels
294} // namespace openpower