blob: e9d9fdf297366bf011850fb6358780f7a487d68f [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 Spinler6ea4d5f2020-05-20 13:31:07 -050037 MOCK_METHOD(const std::vector<std::string>&, getSystemNames, (),
38 (const override));
Matt Spinler5fb24c12020-06-04 11:21:33 -050039 MOCK_METHOD(std::string, expandLocationCode, (const std::string&, uint16_t),
40 (const override));
41 MOCK_METHOD(std::string, getInventoryFromLocCode,
Matt Spinler2f9225a2020-08-05 12:58:49 -050042 (const std::string&, uint16_t, bool), (const override));
Matt Spinlerf60ac272019-12-11 13:47:50 -060043
Matt Spinler34a904c2020-08-05 14:53:28 -050044 MOCK_METHOD(std::string, getFaultLEDGroup, (const std::string&),
45 (const override));
46
47 MOCK_METHOD(void, assertLEDGroup, (const std::string&, bool),
48 (const override));
49
Matt Spinlerf60ac272019-12-11 13:47:50 -060050 void changeHostState(bool newState)
51 {
Matt Spinler4aa23a12020-02-03 15:05:09 -060052 setHostUp(newState);
Matt Spinlerf60ac272019-12-11 13:47:50 -060053 }
54
55 void setHMCManaged(bool managed)
56 {
57 _hmcManaged = managed;
58 }
59};
60
61/**
62 * @brief The mock HostInterface class
Matt Spinler5342d9a2019-12-12 11:03:39 -060063 *
64 * This replaces the PLDM calls with a FIFO for the asynchronous
65 * responses.
Matt Spinlerf60ac272019-12-11 13:47:50 -060066 */
67class MockHostInterface : public HostInterface
68{
69 public:
Matt Spinler5342d9a2019-12-12 11:03:39 -060070 /**
71 * @brief Constructor
72 *
73 * @param[in] event - The sd_event object
74 * @param[in] dataIface - The DataInterface class
75 */
Matt Spinlerf60ac272019-12-11 13:47:50 -060076 MockHostInterface(sd_event* event, DataInterfaceBase& dataIface) :
77 HostInterface(event, dataIface)
78 {
Matt Spinler5342d9a2019-12-12 11:03:39 -060079 char templ[] = "/tmp/cmdfifoXXXXXX";
80 std::filesystem::path dir = mkdtemp(templ);
81 _fifo = dir / "fifo";
Matt Spinlerf60ac272019-12-11 13:47:50 -060082 }
83
Matt Spinler5342d9a2019-12-12 11:03:39 -060084 /**
85 * @brief Destructor
86 */
Matt Spinlerf60ac272019-12-11 13:47:50 -060087 virtual ~MockHostInterface()
88 {
Matt Spinler5342d9a2019-12-12 11:03:39 -060089 std::filesystem::remove_all(_fifo.parent_path());
Matt Spinlerf60ac272019-12-11 13:47:50 -060090 }
91
92 MOCK_METHOD(CmdStatus, sendNewLogCmd, (uint32_t, uint32_t), (override));
93
Matt Spinler5342d9a2019-12-12 11:03:39 -060094 /**
95 * @brief Cancels waiting for a command response
96 */
97 virtual void cancelCmd() override
98 {
99 _inProgress = false;
100 _source = nullptr;
101 }
102
103 /**
104 * @brief Returns the amount of time to wait before retrying after
105 * a failed send command.
106 *
107 * @return milliseconds - The amount of time to wait
108 */
109 virtual std::chrono::milliseconds getSendRetryDelay() const override
110 {
111 return std::chrono::milliseconds(2);
112 }
113
114 /**
115 * @brief Returns the amount of time to wait before retrying after
116 * a command receive.
117 *
118 * @return milliseconds - The amount of time to wait
119 */
120 virtual std::chrono::milliseconds getReceiveRetryDelay() const override
121 {
122 return std::chrono::milliseconds(2);
123 }
124
125 /**
Matt Spinler41293cb2019-12-12 13:11:09 -0600126 * @brief Returns the amount of time to wait before retrying if the
127 * host firmware's PEL storage was full and it can't store
128 * any more logs until it is freed up somehow.
129 *
130 * @return milliseconds - The amount of time to wait
131 */
132 virtual std::chrono::milliseconds getHostFullRetryDelay() const override
133 {
Matt Spinler6aae6a02020-02-07 12:46:07 -0600134 return std::chrono::milliseconds(400);
Matt Spinler41293cb2019-12-12 13:11:09 -0600135 }
136
137 /**
Matt Spinler5342d9a2019-12-12 11:03:39 -0600138 * @brief Returns the number of commands processed
139 */
140 size_t numCmdsProcessed() const
141 {
142 return _cmdsProcessed;
143 }
144
145 /**
146 * @brief Writes the data passed in to the FIFO
147 *
148 * @param[in] hostResponse - use a 0 to indicate success
149 *
150 * @return CmdStatus - success or failure
151 */
152 CmdStatus send(uint8_t hostResponse)
153 {
154 // Create a FIFO once.
155 if (!std::filesystem::exists(_fifo))
156 {
157 if (mkfifo(_fifo.c_str(), 0622))
158 {
159 ADD_FAILURE() << "Failed mkfifo " << _fifo << strerror(errno);
160 exit(-1);
161 }
162 }
163
164 // Open it and register the reponse callback to
165 // be used on FD activity.
166 int fd = open(_fifo.c_str(), O_NONBLOCK | O_RDWR);
167 EXPECT_TRUE(fd >= 0) << "Unable to open FIFO";
168
169 auto callback = [this](sdeventplus::source::IO& source, int fd,
170 uint32_t events) {
171 this->receive(source, fd, events);
172 };
173
174 try
175 {
176 _source = std::make_unique<sdeventplus::source::IO>(
177 _event, fd, EPOLLIN,
178 std::bind(callback, std::placeholders::_1,
179 std::placeholders::_2, std::placeholders::_3));
180 }
181 catch (std::exception& e)
182 {
183 ADD_FAILURE() << "Event exception: " << e.what();
184 close(fd);
185 return CmdStatus::failure;
186 }
187
188 // Write the fake host reponse to the FIFO
189 auto bytesWritten = write(fd, &hostResponse, sizeof(hostResponse));
190 EXPECT_EQ(bytesWritten, sizeof(hostResponse));
191
192 _inProgress = true;
193
194 return CmdStatus::success;
195 }
196
Matt Spinlerf60ac272019-12-11 13:47:50 -0600197 protected:
Matt Spinler5342d9a2019-12-12 11:03:39 -0600198 /**
199 * @brief Reads the data written to the fifo and then calls
200 * the subscriber's callback.
201 *
202 * Nonzero data indicates a command failure (for testing bad path).
203 *
204 * @param[in] source - The event source object
205 * @param[in] fd - The file descriptor used
206 * @param[in] events - The event bits
207 */
Matt Spinlerf60ac272019-12-11 13:47:50 -0600208 void receive(sdeventplus::source::IO& source, int fd,
209 uint32_t events) override
210 {
Matt Spinler5342d9a2019-12-12 11:03:39 -0600211 if (!(events & EPOLLIN))
212 {
213 return;
214 }
215
216 _inProgress = false;
217
218 int newFD = open(_fifo.c_str(), O_NONBLOCK | O_RDONLY);
219 ASSERT_TRUE(newFD >= 0) << "Failed to open FIFO";
220
221 // Read the host success/failure response from the FIFO.
222 uint8_t data;
223 auto bytesRead = read(newFD, &data, sizeof(data));
224 EXPECT_EQ(bytesRead, sizeof(data));
225
226 close(newFD);
227
228 ResponseStatus status = ResponseStatus::success;
229 if (data != 0)
230 {
231 status = ResponseStatus::failure;
232 }
233
Matt Spinlera44efe42020-03-03 10:30:16 -0600234 callResponseFunc(status);
Matt Spinler5342d9a2019-12-12 11:03:39 -0600235
Matt Spinlerf60ac272019-12-11 13:47:50 -0600236 // Keep account of the number of commands responses for testing.
237 _cmdsProcessed++;
238 }
239
240 private:
Matt Spinler5342d9a2019-12-12 11:03:39 -0600241 /**
242 * @brief The event source for the fifo
243 */
244 std::unique_ptr<sdeventplus::source::IO> _source;
245
246 /**
247 * @brief the path to the fifo
248 */
249 std::filesystem::path _fifo;
250
251 /**
252 * @brief The number of commands processed
253 */
Matt Spinlerf60ac272019-12-11 13:47:50 -0600254 size_t _cmdsProcessed = 0;
Matt Spinler09d64002019-09-11 14:29:46 -0500255};
256
257} // namespace pels
258} // namespace openpower