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 #include "test/test_instance_id.hpp"
10 
11 #include <libpldm/entity.h>
12 #include <libpldm/oem/ibm/entity.h>
13 
14 #include <sdeventplus/event.hpp>
15 
16 using namespace pldm::utils;
17 using namespace pldm::responder;
18 using namespace pldm::responder::pdr;
19 using namespace pldm::responder::pdr_utils;
20 using namespace pldm::responder::oem_ibm_platform;
21 
22 class MockCodeUpdate : public CodeUpdate
23 {
24   public:
25     MockCodeUpdate(const pldm::utils::DBusHandler* dBusIntf) :
26         CodeUpdate(dBusIntf)
27     {}
28 
29     MOCK_METHOD(void, setVersions, (), (override));
30 };
31 
32 class MockOemPlatformHandler : public oem_ibm_platform::Handler
33 {
34   public:
35     MockOemPlatformHandler(const pldm::utils::DBusHandler* dBusIntf,
36                            pldm::responder::CodeUpdate* codeUpdate, int mctp_fd,
37                            uint8_t mctp_eid, pldm::InstanceIdDb& instanceIdDb,
38                            sdeventplus::Event& event) :
39         oem_ibm_platform::Handler(dBusIntf, codeUpdate, mctp_fd, mctp_eid,
40                                   instanceIdDb, event, nullptr)
41     {}
42     MOCK_METHOD(uint16_t, getNextEffecterId, ());
43     MOCK_METHOD(uint16_t, getNextSensorId, ());
44 };
45 
46 TEST(OemSetStateEffecterStatesHandler, testGoodRequest)
47 {
48     uint16_t entityID_ = PLDM_OEM_IBM_ENTITY_FIRMWARE_UPDATE;
49     uint16_t stateSetId_ = PLDM_OEM_IBM_BOOT_STATE;
50     uint16_t entityInstance_ = 0;
51     uint8_t compSensorCnt_ = 1;
52     uint16_t effecterId = 0xA;
53     TestInstanceIdDb instanceIdDb;
54 
55     sdbusplus::bus_t bus(sdbusplus::bus::new_default());
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, instanceIdDb,
66         event, 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(rc, PLDM_SUCCESS);
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(rc, PLDM_SUCCESS);
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 = encodeEventMsg(PLDM_SENSOR_EVENT, sensorEventDataVec, requestMsg,
150                              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 = encodeEventMsg(PLDM_SENSOR_EVENT, sensorEventDataVec, requestMsg,
161                              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     std::filesystem::path dbPath;
191     TestInstanceIdDb instanceIdDb;
192     auto mockDbusHandler = std::make_unique<MockdBusHandler>();
193     auto event = sdeventplus::Event::get_default();
194     std::unique_ptr<CodeUpdate> mockCodeUpdate =
195         std::make_unique<MockCodeUpdate>(mockDbusHandler.get());
196     std::unique_ptr<oem_ibm_platform::Handler> mockoemPlatformHandler =
197         std::make_unique<MockOemPlatformHandler>(mockDbusHandler.get(),
198                                                  mockCodeUpdate.get(), 0x1, 0x9,
199                                                  instanceIdDb, event);
200     Repo inRepo(inPDRRepo);
201 
202     mockoemPlatformHandler->buildOEMPDR(inRepo);
203     ASSERT_EQ(inRepo.empty(), false);
204 
205     pdr_utils::PdrEntry e;
206 
207     // Test for effecter number 1, for current boot side state
208     auto record1 = pdr::getRecordByHandle(inRepo, 1, e);
209     ASSERT_NE(record1, nullptr);
210 
211     pldm_state_effecter_pdr* pdr =
212         reinterpret_cast<pldm_state_effecter_pdr*>(e.data);
213 
214     ASSERT_EQ(pdr->hdr.record_handle, 1);
215     ASSERT_EQ(pdr->hdr.version, 1);
216     ASSERT_EQ(pdr->hdr.type, PLDM_STATE_EFFECTER_PDR);
217     ASSERT_EQ(pdr->hdr.record_change_num, 0);
218     ASSERT_EQ(pdr->hdr.length, 16);
219     ASSERT_EQ(pdr->terminus_handle, TERMINUS_HANDLE);
220     ASSERT_EQ(pdr->entity_type, PLDM_OEM_IBM_ENTITY_FIRMWARE_UPDATE);
221     ASSERT_EQ(pdr->entity_instance, 0);
222     ASSERT_EQ(pdr->container_id, 1);
223     ASSERT_EQ(pdr->effecter_semantic_id, 0);
224     ASSERT_EQ(pdr->effecter_init, PLDM_NO_INIT);
225     ASSERT_EQ(pdr->has_description_pdr, false);
226     ASSERT_EQ(pdr->composite_effecter_count, 1);
227     state_effecter_possible_states* states =
228         reinterpret_cast<state_effecter_possible_states*>(pdr->possible_states);
229     ASSERT_EQ(states->state_set_id, 32769);
230     ASSERT_EQ(states->possible_states_size, 2);
231     bitfield8_t bf1{};
232     bf1.byte = 6;
233     ASSERT_EQ(states->states[0].byte, bf1.byte);
234 
235     // Test for effecter number 2, for next boot side state
236     auto record2 = pdr::getRecordByHandle(inRepo, 2, e);
237     ASSERT_NE(record2, nullptr);
238 
239     pdr = reinterpret_cast<pldm_state_effecter_pdr*>(e.data);
240 
241     ASSERT_EQ(pdr->hdr.record_handle, 2);
242     ASSERT_EQ(pdr->hdr.version, 1);
243     ASSERT_EQ(pdr->hdr.type, PLDM_STATE_EFFECTER_PDR);
244     ASSERT_EQ(pdr->hdr.record_change_num, 0);
245     ASSERT_EQ(pdr->hdr.length, 16);
246     ASSERT_EQ(pdr->terminus_handle, TERMINUS_HANDLE);
247     ASSERT_EQ(pdr->entity_type, PLDM_OEM_IBM_ENTITY_FIRMWARE_UPDATE);
248     ASSERT_EQ(pdr->entity_instance, 1);
249     ASSERT_EQ(pdr->container_id, 1);
250     ASSERT_EQ(pdr->effecter_semantic_id, 0);
251     ASSERT_EQ(pdr->effecter_init, PLDM_NO_INIT);
252     ASSERT_EQ(pdr->has_description_pdr, false);
253     ASSERT_EQ(pdr->composite_effecter_count, 1);
254     states =
255         reinterpret_cast<state_effecter_possible_states*>(pdr->possible_states);
256     ASSERT_EQ(states->state_set_id, 32769);
257     ASSERT_EQ(states->possible_states_size, 2);
258     bitfield8_t bf2{};
259     bf2.byte = 6;
260     ASSERT_EQ(states->states[0].byte, bf2.byte);
261 
262     // Test for effecter number 3, for firmware update state control
263     auto record3 = pdr::getRecordByHandle(inRepo, 3, e);
264     ASSERT_NE(record3, nullptr);
265 
266     pdr = reinterpret_cast<pldm_state_effecter_pdr*>(e.data);
267 
268     ASSERT_EQ(pdr->hdr.record_handle, 3);
269     ASSERT_EQ(pdr->hdr.version, 1);
270     ASSERT_EQ(pdr->hdr.type, PLDM_STATE_EFFECTER_PDR);
271     ASSERT_EQ(pdr->hdr.record_change_num, 0);
272     ASSERT_EQ(pdr->hdr.length, 16);
273     ASSERT_EQ(pdr->terminus_handle, TERMINUS_HANDLE);
274     ASSERT_EQ(pdr->entity_type, PLDM_OEM_IBM_ENTITY_FIRMWARE_UPDATE);
275     ASSERT_EQ(pdr->entity_instance, 0);
276     ASSERT_EQ(pdr->container_id, 1);
277     ASSERT_EQ(pdr->effecter_semantic_id, 0);
278     ASSERT_EQ(pdr->effecter_init, PLDM_NO_INIT);
279     ASSERT_EQ(pdr->has_description_pdr, false);
280     ASSERT_EQ(pdr->composite_effecter_count, 1);
281     states =
282         reinterpret_cast<state_effecter_possible_states*>(pdr->possible_states);
283     ASSERT_EQ(states->state_set_id, 32768);
284     ASSERT_EQ(states->possible_states_size, 2);
285     bitfield8_t bf3{};
286     bf3.byte = 126;
287     ASSERT_EQ(states->states[0].byte, bf3.byte);
288 
289     pldm_pdr_destroy(inPDRRepo);
290 }
291 
292 TEST(generateStateSensorOEMPDR, testGoodRequest)
293 {
294     auto inPDRRepo = pldm_pdr_init();
295     sdbusplus::bus_t bus(sdbusplus::bus::new_default());
296     std::filesystem::path dbPath;
297     TestInstanceIdDb instanceIdDb;
298 
299     auto mockDbusHandler = std::make_unique<MockdBusHandler>();
300     auto event = sdeventplus::Event::get_default();
301     std::unique_ptr<CodeUpdate> mockCodeUpdate =
302         std::make_unique<MockCodeUpdate>(mockDbusHandler.get());
303     std::unique_ptr<oem_ibm_platform::Handler> mockoemPlatformHandler =
304         std::make_unique<MockOemPlatformHandler>(mockDbusHandler.get(),
305                                                  mockCodeUpdate.get(), 0x1, 0x9,
306                                                  instanceIdDb, event);
307     Repo inRepo(inPDRRepo);
308     mockoemPlatformHandler->buildOEMPDR(inRepo);
309     ASSERT_EQ(inRepo.empty(), false);
310 
311     pdr_utils::PdrEntry e;
312 
313     // Test for sensor number 1, for current boot side state
314     auto record1 = pdr::getRecordByHandle(inRepo, 5, e);
315     ASSERT_NE(record1, nullptr);
316 
317     pldm_state_sensor_pdr* pdr =
318         reinterpret_cast<pldm_state_sensor_pdr*>(e.data);
319 
320     ASSERT_EQ(pdr->hdr.record_handle, 5);
321     ASSERT_EQ(pdr->hdr.version, 1);
322     ASSERT_EQ(pdr->hdr.type, PLDM_STATE_SENSOR_PDR);
323     ASSERT_EQ(pdr->hdr.record_change_num, 0);
324     ASSERT_EQ(pdr->hdr.length, 14);
325     ASSERT_EQ(pdr->terminus_handle, TERMINUS_HANDLE);
326     ASSERT_EQ(pdr->entity_type, PLDM_OEM_IBM_ENTITY_FIRMWARE_UPDATE);
327     ASSERT_EQ(pdr->entity_instance, 0);
328     ASSERT_EQ(pdr->container_id, 1);
329     ASSERT_EQ(pdr->sensor_init, PLDM_NO_INIT);
330     ASSERT_EQ(pdr->sensor_auxiliary_names_pdr, false);
331     ASSERT_EQ(pdr->composite_sensor_count, 1);
332     state_sensor_possible_states* states =
333         reinterpret_cast<state_sensor_possible_states*>(pdr->possible_states);
334     ASSERT_EQ(states->state_set_id, 32769);
335     ASSERT_EQ(states->possible_states_size, 2);
336     bitfield8_t bf1{};
337     bf1.byte = 6;
338     ASSERT_EQ(states->states[0].byte, bf1.byte);
339 
340     // Test for sensor number 2, for next boot side state
341     auto record2 = pdr::getRecordByHandle(inRepo, 6, e);
342     ASSERT_NE(record2, nullptr);
343 
344     pdr = reinterpret_cast<pldm_state_sensor_pdr*>(e.data);
345 
346     ASSERT_EQ(pdr->hdr.record_handle, 6);
347     ASSERT_EQ(pdr->hdr.version, 1);
348     ASSERT_EQ(pdr->hdr.type, PLDM_STATE_SENSOR_PDR);
349     ASSERT_EQ(pdr->hdr.record_change_num, 0);
350     ASSERT_EQ(pdr->hdr.length, 14);
351     ASSERT_EQ(pdr->terminus_handle, TERMINUS_HANDLE);
352     ASSERT_EQ(pdr->entity_type, PLDM_OEM_IBM_ENTITY_FIRMWARE_UPDATE);
353     ASSERT_EQ(pdr->entity_instance, 1);
354     ASSERT_EQ(pdr->container_id, 1);
355     ASSERT_EQ(pdr->sensor_init, PLDM_NO_INIT);
356     ASSERT_EQ(pdr->sensor_auxiliary_names_pdr, false);
357     ASSERT_EQ(pdr->composite_sensor_count, 1);
358     states =
359         reinterpret_cast<state_sensor_possible_states*>(pdr->possible_states);
360     ASSERT_EQ(states->state_set_id, 32769);
361     ASSERT_EQ(states->possible_states_size, 2);
362     bitfield8_t bf2{};
363     bf2.byte = 6;
364     ASSERT_EQ(states->states[0].byte, bf2.byte);
365 
366     // Test for sensor number 3, for firmware update state control
367     auto record3 = pdr::getRecordByHandle(inRepo, 7, e);
368     ASSERT_NE(record3, nullptr);
369 
370     pdr = reinterpret_cast<pldm_state_sensor_pdr*>(e.data);
371 
372     ASSERT_EQ(pdr->hdr.record_handle, 7);
373     ASSERT_EQ(pdr->hdr.version, 1);
374     ASSERT_EQ(pdr->hdr.type, PLDM_STATE_SENSOR_PDR);
375     ASSERT_EQ(pdr->hdr.record_change_num, 0);
376     ASSERT_EQ(pdr->hdr.length, 14);
377     ASSERT_EQ(pdr->terminus_handle, TERMINUS_HANDLE);
378     ASSERT_EQ(pdr->entity_type, PLDM_OEM_IBM_ENTITY_FIRMWARE_UPDATE);
379     ASSERT_EQ(pdr->entity_instance, 0);
380     ASSERT_EQ(pdr->container_id, 1);
381     ASSERT_EQ(pdr->sensor_init, PLDM_NO_INIT);
382     ASSERT_EQ(pdr->sensor_auxiliary_names_pdr, false);
383     ASSERT_EQ(pdr->composite_sensor_count, 1);
384     states =
385         reinterpret_cast<state_sensor_possible_states*>(pdr->possible_states);
386     ASSERT_EQ(states->state_set_id, 32768);
387     ASSERT_EQ(states->possible_states_size, 2);
388     bitfield8_t bf3{};
389     bf3.byte = 126;
390     ASSERT_EQ(states->states[0].byte, bf3.byte);
391 
392     pldm_pdr_destroy(inPDRRepo);
393 }
394