blob: ae8d38515171acaa2de57c1d98435635b107b827 [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:
Matt Spinler784b02e2023-04-25 11:07:55 -050021 MockDataInterface()
22 {
23 ON_CALL(*this, checkDumpStatus)
24 .WillByDefault(
25 ::testing::Return(std::vector<bool>({false, false, false})));
26 }
27
Matt Spinlerf60ac272019-12-11 13:47:50 -060028 MOCK_METHOD(std::string, getMachineTypeModel, (), (const override));
29 MOCK_METHOD(std::string, getMachineSerialNumber, (), (const override));
30 MOCK_METHOD(std::string, getServerFWVersion, (), (const override));
31 MOCK_METHOD(std::string, getBMCFWVersion, (), (const override));
Matt Spinler677381b2020-01-23 10:04:29 -060032 MOCK_METHOD(std::string, getBMCFWVersionID, (), (const override));
Matt Spinler24a85582020-01-27 16:40:21 -060033 MOCK_METHOD(bool, getHostPELEnablement, (), (const override));
Matt Spinler4aa23a12020-02-03 15:05:09 -060034 MOCK_METHOD(std::string, getBMCState, (), (const override));
35 MOCK_METHOD(std::string, getChassisState, (), (const override));
36 MOCK_METHOD(std::string, getHostState, (), (const override));
Matt Spinler075e5ba2020-02-21 15:46:00 -060037 MOCK_METHOD(std::string, getMotherboardCCIN, (), (const override));
Matt Spinler60c4e792020-03-13 13:45:36 -050038 MOCK_METHOD(void, getHWCalloutFields,
Matt Spinler9b90e2a2020-04-14 10:59:04 -050039 (const std::string&, std::string&, std::string&, std::string&),
Matt Spinler60c4e792020-03-13 13:45:36 -050040 (const override));
Matt Spinler9b90e2a2020-04-14 10:59:04 -050041 MOCK_METHOD(std::string, getLocationCode, (const std::string&),
42 (const override));
Matt Spinler1ab66962020-10-29 13:21:44 -050043 MOCK_METHOD(std::vector<std::string>, getSystemNames, (), (const override));
Matt Spinler5fb24c12020-06-04 11:21:33 -050044 MOCK_METHOD(std::string, expandLocationCode, (const std::string&, uint16_t),
45 (const override));
Matt Spinlerbad056b2023-01-25 14:16:57 -060046 MOCK_METHOD(std::vector<std::string>, getInventoryFromLocCode,
Matt Spinler2f9225a2020-08-05 12:58:49 -050047 (const std::string&, uint16_t, bool), (const override));
Matt Spinler34a904c2020-08-05 14:53:28 -050048 MOCK_METHOD(void, assertLEDGroup, (const std::string&, bool),
49 (const override));
Matt Spinler993168d2021-04-07 16:05:03 -050050 MOCK_METHOD(void, setFunctional, (const std::string&, bool),
51 (const override));
Ben Tynere32b7e72021-05-18 12:38:40 -050052 MOCK_METHOD(std::vector<uint8_t>, getSystemIMKeyword, (), (const override));
Sumit Kumar3b8ed7f2021-05-18 12:38:35 -050053 MOCK_METHOD(bool, getQuiesceOnError, (), (const override));
Sumit Kumar76198a22021-07-15 05:59:57 -050054 MOCK_METHOD(void, setCriticalAssociation, (const std::string&),
55 (const override));
Sumit Kumar9d43a722021-08-24 09:46:19 -050056 MOCK_METHOD(std::vector<bool>, checkDumpStatus,
57 (const std::vector<std::string>&), (const override));
Sumit Kumar2c36fdd2021-09-21 03:12:11 -050058 MOCK_METHOD(std::string, getBootState, (), (const override));
Jayanth Othayothecaa2fc2021-11-05 02:02:52 -050059 MOCK_METHOD(void, createGuardRecord,
60 (const std::vector<uint8_t>&, const std::string&,
61 const std::string&),
62 (const override));
Sumit Kumar3e274432021-09-14 06:37:56 -050063 MOCK_METHOD(void, createProgressSRC,
64 (const uint64_t&, const std::vector<uint8_t>&),
65 (const override));
Sumit Kumar027bf282022-01-24 11:25:19 -060066 MOCK_METHOD(std::vector<uint32_t>, getLogIDWithHwIsolation, (),
67 (const override));
Vijay Lobo875b6c72021-10-20 17:38:56 -050068 MOCK_METHOD(std::vector<uint8_t>, getRawProgressSRC, (), (const override));
Arya K Padmand8ae6182024-07-19 06:25:10 -050069 MOCK_METHOD(std::optional<std::vector<uint8_t>>, getDIProperty,
70 (const std::string&), (const override));
harsh-agarwal1d763db32024-09-03 09:18:50 -050071 MOCK_METHOD(DBusPathList, getAssociatedPaths,
72 (const DBusPath&, const DBusPath&, int32_t,
73 const DBusInterfaceList&),
74 (const override));
Matt Spinler34a904c2020-08-05 14:53:28 -050075
Matt Spinlerf60ac272019-12-11 13:47:50 -060076 void changeHostState(bool newState)
77 {
Matt Spinler4aa23a12020-02-03 15:05:09 -060078 setHostUp(newState);
Matt Spinlerf60ac272019-12-11 13:47:50 -060079 }
80
81 void setHMCManaged(bool managed)
82 {
83 _hmcManaged = managed;
84 }
Matt Spinler0dd22c82023-05-04 15:28:12 -050085
86 void fruPresent(const std::string& locationCode)
87 {
88 setFruPresent(locationCode);
89 }
Matt Spinlerf60ac272019-12-11 13:47:50 -060090};
91
92/**
93 * @brief The mock HostInterface class
Matt Spinler5342d9a2019-12-12 11:03:39 -060094 *
95 * This replaces the PLDM calls with a FIFO for the asynchronous
96 * responses.
Matt Spinlerf60ac272019-12-11 13:47:50 -060097 */
98class MockHostInterface : public HostInterface
99{
100 public:
Matt Spinler5342d9a2019-12-12 11:03:39 -0600101 /**
102 * @brief Constructor
103 *
104 * @param[in] event - The sd_event object
105 * @param[in] dataIface - The DataInterface class
106 */
Matt Spinlerf60ac272019-12-11 13:47:50 -0600107 MockHostInterface(sd_event* event, DataInterfaceBase& dataIface) :
108 HostInterface(event, dataIface)
109 {
Matt Spinler5342d9a2019-12-12 11:03:39 -0600110 char templ[] = "/tmp/cmdfifoXXXXXX";
111 std::filesystem::path dir = mkdtemp(templ);
112 _fifo = dir / "fifo";
Matt Spinlerf60ac272019-12-11 13:47:50 -0600113 }
114
Matt Spinler5342d9a2019-12-12 11:03:39 -0600115 /**
116 * @brief Destructor
117 */
Matt Spinlerf60ac272019-12-11 13:47:50 -0600118 virtual ~MockHostInterface()
119 {
Matt Spinler5342d9a2019-12-12 11:03:39 -0600120 std::filesystem::remove_all(_fifo.parent_path());
Matt Spinlerf60ac272019-12-11 13:47:50 -0600121 }
122
123 MOCK_METHOD(CmdStatus, sendNewLogCmd, (uint32_t, uint32_t), (override));
124
Matt Spinler5342d9a2019-12-12 11:03:39 -0600125 /**
126 * @brief Cancels waiting for a command response
127 */
128 virtual void cancelCmd() override
129 {
130 _inProgress = false;
131 _source = nullptr;
132 }
133
134 /**
135 * @brief Returns the amount of time to wait before retrying after
136 * a failed send command.
137 *
138 * @return milliseconds - The amount of time to wait
139 */
140 virtual std::chrono::milliseconds getSendRetryDelay() const override
141 {
142 return std::chrono::milliseconds(2);
143 }
144
145 /**
146 * @brief Returns the amount of time to wait before retrying after
147 * a command receive.
148 *
149 * @return milliseconds - The amount of time to wait
150 */
151 virtual std::chrono::milliseconds getReceiveRetryDelay() const override
152 {
153 return std::chrono::milliseconds(2);
154 }
155
156 /**
Matt Spinler41293cb2019-12-12 13:11:09 -0600157 * @brief Returns the amount of time to wait before retrying if the
158 * host firmware's PEL storage was full and it can't store
159 * any more logs until it is freed up somehow.
160 *
161 * @return milliseconds - The amount of time to wait
162 */
163 virtual std::chrono::milliseconds getHostFullRetryDelay() const override
164 {
Matt Spinler6aae6a02020-02-07 12:46:07 -0600165 return std::chrono::milliseconds(400);
Matt Spinler41293cb2019-12-12 13:11:09 -0600166 }
167
168 /**
Matt Spinlere5f75082022-01-24 16:09:51 -0600169 * @brief Returns the amount of time to wait after the host is up
170 * before sending commands.
171 *
172 * @return milliseconds - The amount of time to wait
173 */
174 virtual std::chrono::milliseconds getHostUpDelay() const override
175 {
176 return std::chrono::milliseconds(0);
177 }
178
179 /**
Matt Spinler5342d9a2019-12-12 11:03:39 -0600180 * @brief Returns the number of commands processed
181 */
182 size_t numCmdsProcessed() const
183 {
184 return _cmdsProcessed;
185 }
186
187 /**
188 * @brief Writes the data passed in to the FIFO
189 *
190 * @param[in] hostResponse - use a 0 to indicate success
191 *
192 * @return CmdStatus - success or failure
193 */
194 CmdStatus send(uint8_t hostResponse)
195 {
196 // Create a FIFO once.
197 if (!std::filesystem::exists(_fifo))
198 {
199 if (mkfifo(_fifo.c_str(), 0622))
200 {
201 ADD_FAILURE() << "Failed mkfifo " << _fifo << strerror(errno);
202 exit(-1);
203 }
204 }
205
206 // Open it and register the reponse callback to
207 // be used on FD activity.
208 int fd = open(_fifo.c_str(), O_NONBLOCK | O_RDWR);
209 EXPECT_TRUE(fd >= 0) << "Unable to open FIFO";
210
Patrick Williams075c7922024-08-16 15:19:49 -0400211 auto callback =
212 [this](sdeventplus::source::IO& source, int fd, uint32_t events) {
213 this->receive(source, fd, events, nullptr);
214 };
Matt Spinler5342d9a2019-12-12 11:03:39 -0600215
216 try
217 {
218 _source = std::make_unique<sdeventplus::source::IO>(
219 _event, fd, EPOLLIN,
220 std::bind(callback, std::placeholders::_1,
221 std::placeholders::_2, std::placeholders::_3));
222 }
Patrick Williams66491c62021-10-06 12:23:37 -0500223 catch (const std::exception& e)
Matt Spinler5342d9a2019-12-12 11:03:39 -0600224 {
225 ADD_FAILURE() << "Event exception: " << e.what();
226 close(fd);
227 return CmdStatus::failure;
228 }
229
230 // Write the fake host reponse to the FIFO
231 auto bytesWritten = write(fd, &hostResponse, sizeof(hostResponse));
232 EXPECT_EQ(bytesWritten, sizeof(hostResponse));
233
234 _inProgress = true;
235
236 return CmdStatus::success;
237 }
238
Matt Spinlerf60ac272019-12-11 13:47:50 -0600239 protected:
Matt Spinler5342d9a2019-12-12 11:03:39 -0600240 /**
241 * @brief Reads the data written to the fifo and then calls
242 * the subscriber's callback.
243 *
244 * Nonzero data indicates a command failure (for testing bad path).
245 *
246 * @param[in] source - The event source object
247 * @param[in] fd - The file descriptor used
248 * @param[in] events - The event bits
249 */
Patrick Williamsd26fa3e2021-04-21 15:22:23 -0500250 void receive(sdeventplus::source::IO& /*source*/, int /*fd*/,
Lakshmi Yadlapati0387a742024-07-01 17:04:37 -0500251 uint32_t events, pldm_transport* /*transport*/) override
Matt Spinlerf60ac272019-12-11 13:47:50 -0600252 {
Matt Spinler5342d9a2019-12-12 11:03:39 -0600253 if (!(events & EPOLLIN))
254 {
255 return;
256 }
257
258 _inProgress = false;
259
260 int newFD = open(_fifo.c_str(), O_NONBLOCK | O_RDONLY);
261 ASSERT_TRUE(newFD >= 0) << "Failed to open FIFO";
262
263 // Read the host success/failure response from the FIFO.
264 uint8_t data;
265 auto bytesRead = read(newFD, &data, sizeof(data));
266 EXPECT_EQ(bytesRead, sizeof(data));
267
268 close(newFD);
269
270 ResponseStatus status = ResponseStatus::success;
271 if (data != 0)
272 {
273 status = ResponseStatus::failure;
274 }
275
Matt Spinlera44efe42020-03-03 10:30:16 -0600276 callResponseFunc(status);
Matt Spinler5342d9a2019-12-12 11:03:39 -0600277
Matt Spinlerf60ac272019-12-11 13:47:50 -0600278 // Keep account of the number of commands responses for testing.
279 _cmdsProcessed++;
280 }
281
282 private:
Matt Spinler5342d9a2019-12-12 11:03:39 -0600283 /**
284 * @brief The event source for the fifo
285 */
286 std::unique_ptr<sdeventplus::source::IO> _source;
287
288 /**
289 * @brief the path to the fifo
290 */
291 std::filesystem::path _fifo;
292
293 /**
294 * @brief The number of commands processed
295 */
Matt Spinlerf60ac272019-12-11 13:47:50 -0600296 size_t _cmdsProcessed = 0;
Matt Spinler09d64002019-09-11 14:29:46 -0500297};
298
Matt Spinlerd96fa602022-12-15 11:11:26 -0600299class MockJournal : public JournalBase
300{
301 public:
302 MockJournal() {}
303
304 MOCK_METHOD(std::vector<std::string>, getMessages,
305 (const std::string&, size_t), (const override));
Matt Spinler9d921092022-12-15 11:54:49 -0600306
307 MOCK_METHOD(void, sync, (), (const override));
Matt Spinlerd96fa602022-12-15 11:11:26 -0600308};
309
Matt Spinler09d64002019-09-11 14:29:46 -0500310} // namespace pels
311} // namespace openpower