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