1 #include "libpldm/entity.h"
2 
3 #include "common/test/mocked_utils.hpp"
4 #include "common/utils.hpp"
5 #include "libpldmresponder/event_parser.hpp"
6 #include "libpldmresponder/pdr.hpp"
7 #include "libpldmresponder/pdr_utils.hpp"
8 #include "libpldmresponder/platform.hpp"
9 #include "oem/ibm/libpldmresponder/inband_code_update.hpp"
10 #include "oem/ibm/libpldmresponder/oem_ibm_handler.hpp"
11 
12 #include <libpldm/entity_oem_ibm.h>
13 
14 #include <sdeventplus/event.hpp>
15 
16 #include <iostream>
17 
18 using namespace pldm::dbus_api;
19 using namespace pldm::utils;
20 using namespace pldm::responder;
21 using namespace pldm::responder::pdr;
22 using namespace pldm::responder::pdr_utils;
23 using namespace pldm::responder::oem_ibm_platform;
24 
25 class MockCodeUpdate : public CodeUpdate
26 {
27   public:
28     MockCodeUpdate(const pldm::utils::DBusHandler* dBusIntf) :
29         CodeUpdate(dBusIntf)
30     {}
31 
32     MOCK_METHOD(void, setVersions, (), (override));
33 };
34 
35 class MockOemPlatformHandler : public oem_ibm_platform::Handler
36 {
37   public:
38     MockOemPlatformHandler(const pldm::utils::DBusHandler* dBusIntf,
39                            pldm::responder::CodeUpdate* codeUpdate, int mctp_fd,
40                            uint8_t mctp_eid, Requester& requester,
41                            sdeventplus::Event& event) :
42         oem_ibm_platform::Handler(dBusIntf, codeUpdate, mctp_fd, mctp_eid,
43                                   requester, event, nullptr)
44     {}
45     MOCK_METHOD(uint16_t, getNextEffecterId, ());
46     MOCK_METHOD(uint16_t, getNextSensorId, ());
47 };
48 
49 TEST(OemSetStateEffecterStatesHandler, testGoodRequest)
50 {
51     uint16_t entityID_ = PLDM_OEM_IBM_ENTITY_FIRMWARE_UPDATE;
52     uint16_t stateSetId_ = PLDM_OEM_IBM_BOOT_STATE;
53     uint16_t entityInstance_ = 0;
54     uint8_t compSensorCnt_ = 1;
55     uint16_t effecterId = 0xA;
56     sdbusplus::bus_t bus(sdbusplus::bus::new_default());
57     Requester requester(bus, "/abc/def");
58     auto event = sdeventplus::Event::get_default();
59     std::vector<get_sensor_state_field> stateField;
60 
61     auto mockDbusHandler = std::make_unique<MockdBusHandler>();
62     std::unique_ptr<CodeUpdate> mockCodeUpdate =
63         std::make_unique<MockCodeUpdate>(mockDbusHandler.get());
64     std::unique_ptr<oem_platform::Handler> oemPlatformHandler{};
65 
66     oemPlatformHandler = std::make_unique<oem_ibm_platform::Handler>(
67         mockDbusHandler.get(), mockCodeUpdate.get(), 0x1, 0x9, requester, event,
68         nullptr);
69 
70     auto rc = oemPlatformHandler->getOemStateSensorReadingsHandler(
71         entityID_, entityInstance_, stateSetId_, compSensorCnt_, stateField);
72 
73     ASSERT_EQ(rc, PLDM_SUCCESS);
74     ASSERT_EQ(stateField.size(), 1);
75     ASSERT_EQ(stateField[0].event_state, tSideNum);
76     ASSERT_EQ(stateField[0].sensor_op_state, PLDM_SENSOR_ENABLED);
77     ASSERT_EQ(stateField[0].present_state, PLDM_SENSOR_UNKNOWN);
78     ASSERT_EQ(stateField[0].previous_state, PLDM_SENSOR_UNKNOWN);
79 
80     entityInstance_ = 1;
81 
82     std::vector<get_sensor_state_field> stateField1;
83     rc = oemPlatformHandler->getOemStateSensorReadingsHandler(
84         entityID_, entityInstance_, stateSetId_, compSensorCnt_, stateField1);
85     ASSERT_EQ(stateField1.size(), 1);
86     ASSERT_EQ(stateField1[0].event_state, tSideNum);
87 
88     entityInstance_ = 2;
89     rc = oemPlatformHandler->getOemStateSensorReadingsHandler(
90         entityID_, entityInstance_, stateSetId_, compSensorCnt_, stateField1);
91     ASSERT_EQ(stateField1[0].event_state, PLDM_SENSOR_UNKNOWN);
92 
93     entityID_ = 40;
94     stateSetId_ = 50;
95     rc = oemPlatformHandler->getOemStateSensorReadingsHandler(
96         entityID_, entityInstance_, stateSetId_, compSensorCnt_, stateField1);
97     ASSERT_EQ(rc, PLDM_PLATFORM_INVALID_STATE_VALUE);
98 
99     entityID_ = PLDM_OEM_IBM_ENTITY_FIRMWARE_UPDATE;
100     entityInstance_ = 0;
101     stateSetId_ = PLDM_OEM_IBM_BOOT_STATE;
102     compSensorCnt_ = 1;
103 
104     std::vector<set_effecter_state_field> setEffecterStateField;
105     setEffecterStateField.push_back({PLDM_REQUEST_SET, pSideNum});
106 
107     rc = oemPlatformHandler->oemSetStateEffecterStatesHandler(
108         entityID_, entityInstance_, stateSetId_, compSensorCnt_,
109         setEffecterStateField, effecterId);
110     ASSERT_EQ(rc, PLDM_SUCCESS);
111 
112     entityInstance_ = 2;
113     rc = oemPlatformHandler->oemSetStateEffecterStatesHandler(
114         entityID_, entityInstance_, stateSetId_, compSensorCnt_,
115         setEffecterStateField, effecterId);
116 
117     ASSERT_EQ(rc, PLDM_PLATFORM_INVALID_STATE_VALUE);
118 
119     entityID_ = 34;
120     stateSetId_ = 99;
121     entityInstance_ = 0;
122     rc = oemPlatformHandler->oemSetStateEffecterStatesHandler(
123         entityID_, entityInstance_, stateSetId_, compSensorCnt_,
124         setEffecterStateField, effecterId);
125     ASSERT_EQ(rc, PLDM_PLATFORM_SET_EFFECTER_UNSUPPORTED_SENSORSTATE);
126 }
127 
128 TEST(EncodeCodeUpdateEvent, testGoodRequest)
129 {
130     size_t sensorEventSize = PLDM_SENSOR_EVENT_DATA_MIN_LENGTH + 1;
131     std::vector<uint8_t> sensorEventDataVec{};
132     sensorEventDataVec.resize(sensorEventSize);
133 
134     auto eventData = reinterpret_cast<struct pldm_sensor_event_data*>(
135         sensorEventDataVec.data());
136     eventData->sensor_id = 0xA;
137     eventData->sensor_event_class_type = PLDM_SENSOR_OP_STATE;
138 
139     auto opStateSensorEventData =
140         reinterpret_cast<struct pldm_sensor_event_sensor_op_state*>(
141             sensorEventDataVec.data());
142     opStateSensorEventData->present_op_state = uint8_t(CodeUpdateState::START);
143     opStateSensorEventData->previous_op_state = uint8_t(CodeUpdateState::END);
144 
145     std::vector<uint8_t> requestMsg(sizeof(pldm_msg_hdr) +
146                                     PLDM_PLATFORM_EVENT_MESSAGE_MIN_REQ_BYTES +
147                                     sensorEventDataVec.size());
148 
149     auto rc =
150         encodeEventMsg(PLDM_SENSOR_EVENT, sensorEventDataVec, requestMsg, 0x1);
151 
152     EXPECT_EQ(rc, PLDM_SUCCESS);
153 }
154 
155 TEST(EncodeCodeUpdate, testBadRequest)
156 {
157     std::vector<uint8_t> requestMsg;
158     std::vector<uint8_t> sensorEventDataVec{};
159 
160     auto rc =
161         encodeEventMsg(PLDM_SENSOR_EVENT, sensorEventDataVec, requestMsg, 0x1);
162 
163     EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
164 }
165 
166 TEST(clearDirPath, testClearDirPath)
167 {
168     char dirPath[] = "/tmp/testClearDir/";
169     fs::path dir(dirPath);
170     fs::create_directories(dir);
171     struct stat buffer;
172     ASSERT_EQ(stat(dirPath, &buffer), 0);
173     char filePath[] = "/tmp/testClearDir/file.txt";
174     std::ofstream file(filePath);
175     ASSERT_EQ(stat(filePath, &buffer), 0);
176 
177     auto mockDbusHandler = std::make_unique<MockdBusHandler>();
178     std::unique_ptr<CodeUpdate> mockCodeUpdate =
179         std::make_unique<MockCodeUpdate>(mockDbusHandler.get());
180 
181     mockCodeUpdate->clearDirPath(dirPath);
182     ASSERT_EQ(stat(filePath, &buffer), -1);
183     ASSERT_EQ(stat(dirPath, &buffer), 0);
184 }
185 
186 TEST(generateStateEffecterOEMPDR, testGoodRequest)
187 {
188     auto inPDRRepo = pldm_pdr_init();
189     sdbusplus::bus_t bus(sdbusplus::bus::new_default());
190     Requester requester(bus, "/abc/def");
191     auto mockDbusHandler = std::make_unique<MockdBusHandler>();
192     auto event = sdeventplus::Event::get_default();
193     std::unique_ptr<CodeUpdate> mockCodeUpdate =
194         std::make_unique<MockCodeUpdate>(mockDbusHandler.get());
195     std::unique_ptr<oem_ibm_platform::Handler> mockoemPlatformHandler =
196         std::make_unique<MockOemPlatformHandler>(mockDbusHandler.get(),
197                                                  mockCodeUpdate.get(), 0x1, 0x9,
198                                                  requester, event);
199     Repo inRepo(inPDRRepo);
200 
201     mockoemPlatformHandler->buildOEMPDR(inRepo);
202     ASSERT_EQ(inRepo.empty(), false);
203 
204     pdr_utils::PdrEntry e;
205 
206     // Test for effecter number 1, for current boot side state
207     auto record1 = pdr::getRecordByHandle(inRepo, 1, e);
208     ASSERT_NE(record1, nullptr);
209 
210     pldm_state_effecter_pdr* pdr =
211         reinterpret_cast<pldm_state_effecter_pdr*>(e.data);
212 
213     ASSERT_EQ(pdr->hdr.record_handle, 1);
214     ASSERT_EQ(pdr->hdr.version, 1);
215     ASSERT_EQ(pdr->hdr.type, PLDM_STATE_EFFECTER_PDR);
216     ASSERT_EQ(pdr->hdr.record_change_num, 0);
217     ASSERT_EQ(pdr->hdr.length, 16);
218     ASSERT_EQ(pdr->terminus_handle, TERMINUS_HANDLE);
219     ASSERT_EQ(pdr->entity_type, PLDM_OEM_IBM_ENTITY_FIRMWARE_UPDATE);
220     ASSERT_EQ(pdr->entity_instance, 0);
221     ASSERT_EQ(pdr->container_id, 0);
222     ASSERT_EQ(pdr->effecter_semantic_id, 0);
223     ASSERT_EQ(pdr->effecter_init, PLDM_NO_INIT);
224     ASSERT_EQ(pdr->has_description_pdr, false);
225     ASSERT_EQ(pdr->composite_effecter_count, 1);
226     state_effecter_possible_states* states =
227         reinterpret_cast<state_effecter_possible_states*>(pdr->possible_states);
228     ASSERT_EQ(states->state_set_id, 32769);
229     ASSERT_EQ(states->possible_states_size, 2);
230     bitfield8_t bf1{};
231     bf1.byte = 6;
232     ASSERT_EQ(states->states[0].byte, bf1.byte);
233 
234     // Test for effecter number 2, for next boot side state
235     auto record2 = pdr::getRecordByHandle(inRepo, 2, e);
236     ASSERT_NE(record2, nullptr);
237 
238     pdr = reinterpret_cast<pldm_state_effecter_pdr*>(e.data);
239 
240     ASSERT_EQ(pdr->hdr.record_handle, 2);
241     ASSERT_EQ(pdr->hdr.version, 1);
242     ASSERT_EQ(pdr->hdr.type, PLDM_STATE_EFFECTER_PDR);
243     ASSERT_EQ(pdr->hdr.record_change_num, 0);
244     ASSERT_EQ(pdr->hdr.length, 16);
245     ASSERT_EQ(pdr->terminus_handle, TERMINUS_HANDLE);
246     ASSERT_EQ(pdr->entity_type, PLDM_OEM_IBM_ENTITY_FIRMWARE_UPDATE);
247     ASSERT_EQ(pdr->entity_instance, 1);
248     ASSERT_EQ(pdr->container_id, 0);
249     ASSERT_EQ(pdr->effecter_semantic_id, 0);
250     ASSERT_EQ(pdr->effecter_init, PLDM_NO_INIT);
251     ASSERT_EQ(pdr->has_description_pdr, false);
252     ASSERT_EQ(pdr->composite_effecter_count, 1);
253     states =
254         reinterpret_cast<state_effecter_possible_states*>(pdr->possible_states);
255     ASSERT_EQ(states->state_set_id, 32769);
256     ASSERT_EQ(states->possible_states_size, 2);
257     bitfield8_t bf2{};
258     bf2.byte = 6;
259     ASSERT_EQ(states->states[0].byte, bf2.byte);
260 
261     // Test for effecter number 3, for firmware update state control
262     auto record3 = pdr::getRecordByHandle(inRepo, 3, e);
263     ASSERT_NE(record3, nullptr);
264 
265     pdr = reinterpret_cast<pldm_state_effecter_pdr*>(e.data);
266 
267     ASSERT_EQ(pdr->hdr.record_handle, 3);
268     ASSERT_EQ(pdr->hdr.version, 1);
269     ASSERT_EQ(pdr->hdr.type, PLDM_STATE_EFFECTER_PDR);
270     ASSERT_EQ(pdr->hdr.record_change_num, 0);
271     ASSERT_EQ(pdr->hdr.length, 16);
272     ASSERT_EQ(pdr->terminus_handle, TERMINUS_HANDLE);
273     ASSERT_EQ(pdr->entity_type, PLDM_OEM_IBM_ENTITY_FIRMWARE_UPDATE);
274     ASSERT_EQ(pdr->entity_instance, 0);
275     ASSERT_EQ(pdr->container_id, 0);
276     ASSERT_EQ(pdr->effecter_semantic_id, 0);
277     ASSERT_EQ(pdr->effecter_init, PLDM_NO_INIT);
278     ASSERT_EQ(pdr->has_description_pdr, false);
279     ASSERT_EQ(pdr->composite_effecter_count, 1);
280     states =
281         reinterpret_cast<state_effecter_possible_states*>(pdr->possible_states);
282     ASSERT_EQ(states->state_set_id, 32768);
283     ASSERT_EQ(states->possible_states_size, 2);
284     bitfield8_t bf3{};
285     bf3.byte = 126;
286     ASSERT_EQ(states->states[0].byte, bf3.byte);
287 
288     pldm_pdr_destroy(inPDRRepo);
289 }
290 
291 TEST(generateStateSensorOEMPDR, testGoodRequest)
292 {
293     auto inPDRRepo = pldm_pdr_init();
294     sdbusplus::bus_t bus(sdbusplus::bus::new_default());
295     Requester requester(bus, "/abc/def");
296 
297     auto mockDbusHandler = std::make_unique<MockdBusHandler>();
298     auto event = sdeventplus::Event::get_default();
299     std::unique_ptr<CodeUpdate> mockCodeUpdate =
300         std::make_unique<MockCodeUpdate>(mockDbusHandler.get());
301     std::unique_ptr<oem_ibm_platform::Handler> mockoemPlatformHandler =
302         std::make_unique<MockOemPlatformHandler>(mockDbusHandler.get(),
303                                                  mockCodeUpdate.get(), 0x1, 0x9,
304                                                  requester, event);
305     Repo inRepo(inPDRRepo);
306     mockoemPlatformHandler->buildOEMPDR(inRepo);
307     ASSERT_EQ(inRepo.empty(), false);
308 
309     pdr_utils::PdrEntry e;
310 
311     // Test for sensor number 1, for current boot side state
312     auto record1 = pdr::getRecordByHandle(inRepo, 5, e);
313     ASSERT_NE(record1, nullptr);
314 
315     pldm_state_sensor_pdr* pdr =
316         reinterpret_cast<pldm_state_sensor_pdr*>(e.data);
317 
318     ASSERT_EQ(pdr->hdr.record_handle, 5);
319     ASSERT_EQ(pdr->hdr.version, 1);
320     ASSERT_EQ(pdr->hdr.type, PLDM_STATE_SENSOR_PDR);
321     ASSERT_EQ(pdr->hdr.record_change_num, 0);
322     ASSERT_EQ(pdr->hdr.length, 14);
323     ASSERT_EQ(pdr->terminus_handle, TERMINUS_HANDLE);
324     ASSERT_EQ(pdr->entity_type, PLDM_OEM_IBM_ENTITY_FIRMWARE_UPDATE);
325     ASSERT_EQ(pdr->entity_instance, 0);
326     ASSERT_EQ(pdr->container_id, 0);
327     ASSERT_EQ(pdr->sensor_init, PLDM_NO_INIT);
328     ASSERT_EQ(pdr->sensor_auxiliary_names_pdr, false);
329     ASSERT_EQ(pdr->composite_sensor_count, 1);
330     state_sensor_possible_states* states =
331         reinterpret_cast<state_sensor_possible_states*>(pdr->possible_states);
332     ASSERT_EQ(states->state_set_id, 32769);
333     ASSERT_EQ(states->possible_states_size, 2);
334     bitfield8_t bf1{};
335     bf1.byte = 6;
336     ASSERT_EQ(states->states[0].byte, bf1.byte);
337 
338     // Test for sensor number 2, for next boot side state
339     auto record2 = pdr::getRecordByHandle(inRepo, 6, e);
340     ASSERT_NE(record2, nullptr);
341 
342     pdr = reinterpret_cast<pldm_state_sensor_pdr*>(e.data);
343 
344     ASSERT_EQ(pdr->hdr.record_handle, 6);
345     ASSERT_EQ(pdr->hdr.version, 1);
346     ASSERT_EQ(pdr->hdr.type, PLDM_STATE_SENSOR_PDR);
347     ASSERT_EQ(pdr->hdr.record_change_num, 0);
348     ASSERT_EQ(pdr->hdr.length, 14);
349     ASSERT_EQ(pdr->terminus_handle, TERMINUS_HANDLE);
350     ASSERT_EQ(pdr->entity_type, PLDM_OEM_IBM_ENTITY_FIRMWARE_UPDATE);
351     ASSERT_EQ(pdr->entity_instance, 1);
352     ASSERT_EQ(pdr->container_id, 0);
353     ASSERT_EQ(pdr->sensor_init, PLDM_NO_INIT);
354     ASSERT_EQ(pdr->sensor_auxiliary_names_pdr, false);
355     ASSERT_EQ(pdr->composite_sensor_count, 1);
356     states =
357         reinterpret_cast<state_sensor_possible_states*>(pdr->possible_states);
358     ASSERT_EQ(states->state_set_id, 32769);
359     ASSERT_EQ(states->possible_states_size, 2);
360     bitfield8_t bf2{};
361     bf2.byte = 6;
362     ASSERT_EQ(states->states[0].byte, bf2.byte);
363 
364     // Test for sensor number 3, for firmware update state control
365     auto record3 = pdr::getRecordByHandle(inRepo, 7, e);
366     ASSERT_NE(record3, nullptr);
367 
368     pdr = reinterpret_cast<pldm_state_sensor_pdr*>(e.data);
369 
370     ASSERT_EQ(pdr->hdr.record_handle, 7);
371     ASSERT_EQ(pdr->hdr.version, 1);
372     ASSERT_EQ(pdr->hdr.type, PLDM_STATE_SENSOR_PDR);
373     ASSERT_EQ(pdr->hdr.record_change_num, 0);
374     ASSERT_EQ(pdr->hdr.length, 14);
375     ASSERT_EQ(pdr->terminus_handle, TERMINUS_HANDLE);
376     ASSERT_EQ(pdr->entity_type, PLDM_OEM_IBM_ENTITY_FIRMWARE_UPDATE);
377     ASSERT_EQ(pdr->entity_instance, 0);
378     ASSERT_EQ(pdr->container_id, 0);
379     ASSERT_EQ(pdr->sensor_init, PLDM_NO_INIT);
380     ASSERT_EQ(pdr->sensor_auxiliary_names_pdr, false);
381     ASSERT_EQ(pdr->composite_sensor_count, 1);
382     states =
383         reinterpret_cast<state_sensor_possible_states*>(pdr->possible_states);
384     ASSERT_EQ(states->state_set_id, 32768);
385     ASSERT_EQ(states->possible_states_size, 2);
386     bitfield8_t bf3{};
387     bf3.byte = 126;
388     ASSERT_EQ(states->states[0].byte, bf3.byte);
389 
390     pldm_pdr_destroy(inPDRRepo);
391 }
392