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