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 "libpldmresponder/platform_numeric_effecter.hpp"
8 #include "libpldmresponder/platform_state_effecter.hpp"
9 #include "libpldmresponder/platform_state_sensor.hpp"
10 
11 #include <sdbusplus/test/sdbus_mock.hpp>
12 #include <sdeventplus/event.hpp>
13 
14 #include <iostream>
15 
16 using namespace pldm::pdr;
17 using namespace pldm::utils;
18 using namespace pldm::responder;
19 using namespace pldm::responder::platform;
20 using namespace pldm::responder::pdr;
21 using namespace pldm::responder::pdr_utils;
22 
23 using ::testing::_;
24 using ::testing::Return;
25 using ::testing::StrEq;
26 
27 TEST(getPDR, testGoodPath)
28 {
29     std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_GET_PDR_REQ_BYTES>
30         requestPayload{};
31     auto req = reinterpret_cast<pldm_msg*>(requestPayload.data());
32     size_t requestPayloadLength = requestPayload.size() - sizeof(pldm_msg_hdr);
33 
34     struct pldm_get_pdr_req* request =
35         reinterpret_cast<struct pldm_get_pdr_req*>(req->payload);
36     request->request_count = 100;
37 
38     MockdBusHandler mockedUtils;
39     EXPECT_CALL(mockedUtils, getService(StrEq("/foo/bar"), _))
40         .Times(5)
41         .WillRepeatedly(Return("foo.bar"));
42 
43     auto pdrRepo = pldm_pdr_init();
44     auto event = sdeventplus::Event::get_default();
45     Handler handler(&mockedUtils, "./pdr_jsons/state_effecter/good", pdrRepo,
46                     nullptr, nullptr, nullptr, nullptr, event);
47     Repo repo(pdrRepo);
48     ASSERT_EQ(repo.empty(), false);
49     auto response = handler.getPDR(req, requestPayloadLength);
50     auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
51 
52     struct pldm_get_pdr_resp* resp =
53         reinterpret_cast<struct pldm_get_pdr_resp*>(responsePtr->payload);
54     ASSERT_EQ(PLDM_SUCCESS, resp->completion_code);
55     ASSERT_EQ(2, resp->next_record_handle);
56     ASSERT_EQ(true, resp->response_count != 0);
57 
58     pldm_pdr_hdr* hdr = reinterpret_cast<pldm_pdr_hdr*>(resp->record_data);
59     ASSERT_EQ(hdr->record_handle, 1);
60     ASSERT_EQ(hdr->version, 1);
61 
62     pldm_pdr_destroy(pdrRepo);
63 }
64 
65 TEST(getPDR, testShortRead)
66 {
67     std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_GET_PDR_REQ_BYTES>
68         requestPayload{};
69     auto req = reinterpret_cast<pldm_msg*>(requestPayload.data());
70     size_t requestPayloadLength = requestPayload.size() - sizeof(pldm_msg_hdr);
71 
72     struct pldm_get_pdr_req* request =
73         reinterpret_cast<struct pldm_get_pdr_req*>(req->payload);
74     request->request_count = 1;
75 
76     MockdBusHandler mockedUtils;
77     EXPECT_CALL(mockedUtils, getService(StrEq("/foo/bar"), _))
78         .Times(5)
79         .WillRepeatedly(Return("foo.bar"));
80 
81     auto pdrRepo = pldm_pdr_init();
82     auto event = sdeventplus::Event::get_default();
83     Handler handler(&mockedUtils, "./pdr_jsons/state_effecter/good", pdrRepo,
84                     nullptr, nullptr, nullptr, nullptr, event);
85     Repo repo(pdrRepo);
86     ASSERT_EQ(repo.empty(), false);
87     auto response = handler.getPDR(req, requestPayloadLength);
88     auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
89     struct pldm_get_pdr_resp* resp =
90         reinterpret_cast<struct pldm_get_pdr_resp*>(responsePtr->payload);
91     ASSERT_EQ(PLDM_SUCCESS, resp->completion_code);
92     ASSERT_EQ(1, resp->response_count);
93     pldm_pdr_destroy(pdrRepo);
94 }
95 
96 TEST(getPDR, testBadRecordHandle)
97 {
98     std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_GET_PDR_REQ_BYTES>
99         requestPayload{};
100     auto req = reinterpret_cast<pldm_msg*>(requestPayload.data());
101     size_t requestPayloadLength = requestPayload.size() - sizeof(pldm_msg_hdr);
102 
103     struct pldm_get_pdr_req* request =
104         reinterpret_cast<struct pldm_get_pdr_req*>(req->payload);
105     request->record_handle = 100000;
106     request->request_count = 1;
107 
108     MockdBusHandler mockedUtils;
109     EXPECT_CALL(mockedUtils, getService(StrEq("/foo/bar"), _))
110         .Times(5)
111         .WillRepeatedly(Return("foo.bar"));
112 
113     auto pdrRepo = pldm_pdr_init();
114     auto event = sdeventplus::Event::get_default();
115     Handler handler(&mockedUtils, "./pdr_jsons/state_effecter/good", pdrRepo,
116                     nullptr, nullptr, nullptr, nullptr, event);
117     Repo repo(pdrRepo);
118     ASSERT_EQ(repo.empty(), false);
119     auto response = handler.getPDR(req, requestPayloadLength);
120     auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
121 
122     ASSERT_EQ(responsePtr->payload[0], PLDM_PLATFORM_INVALID_RECORD_HANDLE);
123 
124     pldm_pdr_destroy(pdrRepo);
125 }
126 
127 TEST(getPDR, testNoNextRecord)
128 {
129     std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_GET_PDR_REQ_BYTES>
130         requestPayload{};
131     auto req = reinterpret_cast<pldm_msg*>(requestPayload.data());
132     size_t requestPayloadLength = requestPayload.size() - sizeof(pldm_msg_hdr);
133 
134     struct pldm_get_pdr_req* request =
135         reinterpret_cast<struct pldm_get_pdr_req*>(req->payload);
136     request->record_handle = 1;
137 
138     MockdBusHandler mockedUtils;
139     EXPECT_CALL(mockedUtils, getService(StrEq("/foo/bar"), _))
140         .Times(5)
141         .WillRepeatedly(Return("foo.bar"));
142 
143     auto pdrRepo = pldm_pdr_init();
144     auto event = sdeventplus::Event::get_default();
145     Handler handler(&mockedUtils, "./pdr_jsons/state_effecter/good", pdrRepo,
146                     nullptr, nullptr, nullptr, nullptr, event);
147     Repo repo(pdrRepo);
148     ASSERT_EQ(repo.empty(), false);
149     auto response = handler.getPDR(req, requestPayloadLength);
150     auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
151     struct pldm_get_pdr_resp* resp =
152         reinterpret_cast<struct pldm_get_pdr_resp*>(responsePtr->payload);
153     ASSERT_EQ(PLDM_SUCCESS, resp->completion_code);
154     ASSERT_EQ(2, resp->next_record_handle);
155 
156     pldm_pdr_destroy(pdrRepo);
157 }
158 
159 TEST(getPDR, testFindPDR)
160 {
161     std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_GET_PDR_REQ_BYTES>
162         requestPayload{};
163     auto req = reinterpret_cast<pldm_msg*>(requestPayload.data());
164     size_t requestPayloadLength = requestPayload.size() - sizeof(pldm_msg_hdr);
165 
166     struct pldm_get_pdr_req* request =
167         reinterpret_cast<struct pldm_get_pdr_req*>(req->payload);
168     request->request_count = 100;
169 
170     MockdBusHandler mockedUtils;
171     EXPECT_CALL(mockedUtils, getService(StrEq("/foo/bar"), _))
172         .Times(5)
173         .WillRepeatedly(Return("foo.bar"));
174 
175     auto pdrRepo = pldm_pdr_init();
176     auto event = sdeventplus::Event::get_default();
177     Handler handler(&mockedUtils, "./pdr_jsons/state_effecter/good", pdrRepo,
178                     nullptr, nullptr, nullptr, nullptr, event);
179     Repo repo(pdrRepo);
180     ASSERT_EQ(repo.empty(), false);
181     auto response = handler.getPDR(req, requestPayloadLength);
182 
183     // Let's try to find a PDR of type stateEffecter (= 11) and entity type =
184     // 100
185     bool found = false;
186     uint32_t handle = 0; // start asking for PDRs from recordHandle 0
187     while (!found)
188     {
189         request->record_handle = handle;
190         auto response = handler.getPDR(req, requestPayloadLength);
191         auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
192         struct pldm_get_pdr_resp* resp =
193             reinterpret_cast<struct pldm_get_pdr_resp*>(responsePtr->payload);
194         ASSERT_EQ(PLDM_SUCCESS, resp->completion_code);
195 
196         handle = resp->next_record_handle; // point to the next pdr in case
197                                            // current is not what we want
198 
199         pldm_pdr_hdr* hdr = reinterpret_cast<pldm_pdr_hdr*>(resp->record_data);
200         if (hdr->type == PLDM_STATE_EFFECTER_PDR)
201         {
202             pldm_state_effecter_pdr* pdr =
203                 reinterpret_cast<pldm_state_effecter_pdr*>(resp->record_data);
204             if (pdr->entity_type == 100)
205             {
206                 found = true;
207                 // Rest of the PDR can be accessed as need be
208                 break;
209             }
210         }
211         if (!resp->next_record_handle) // no more records
212         {
213             break;
214         }
215     }
216     ASSERT_EQ(found, true);
217 
218     pldm_pdr_destroy(pdrRepo);
219 }
220 
221 TEST(setStateEffecterStatesHandler, testGoodRequest)
222 {
223     std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_GET_PDR_REQ_BYTES>
224         requestPayload{};
225     auto req = reinterpret_cast<pldm_msg*>(requestPayload.data());
226     size_t requestPayloadLength = requestPayload.size() - sizeof(pldm_msg_hdr);
227 
228     MockdBusHandler mockedUtils;
229     EXPECT_CALL(mockedUtils, getService(StrEq("/foo/bar"), _))
230         .Times(5)
231         .WillRepeatedly(Return("foo.bar"));
232 
233     auto inPDRRepo = pldm_pdr_init();
234     auto outPDRRepo = pldm_pdr_init();
235     Repo outRepo(outPDRRepo);
236     auto event = sdeventplus::Event::get_default();
237     Handler handler(&mockedUtils, "./pdr_jsons/state_effecter/good", inPDRRepo,
238                     nullptr, nullptr, nullptr, nullptr, event);
239     handler.getPDR(req, requestPayloadLength);
240     Repo inRepo(inPDRRepo);
241     getRepoByType(inRepo, outRepo, PLDM_STATE_EFFECTER_PDR);
242     pdr_utils::PdrEntry e;
243     auto record1 = pdr::getRecordByHandle(outRepo, 2, e);
244     ASSERT_NE(record1, nullptr);
245     pldm_state_effecter_pdr* pdr =
246         reinterpret_cast<pldm_state_effecter_pdr*>(e.data);
247     EXPECT_EQ(pdr->hdr.type, PLDM_STATE_EFFECTER_PDR);
248 
249     std::vector<set_effecter_state_field> stateField;
250     stateField.push_back({PLDM_REQUEST_SET, 1});
251     stateField.push_back({PLDM_REQUEST_SET, 1});
252     std::string value = "xyz.openbmc_project.Foo.Bar.V1";
253     PropertyValue propertyValue = value;
254 
255     DBusMapping dbusMapping{"/foo/bar", "xyz.openbmc_project.Foo.Bar",
256                             "propertyName", "string"};
257 
258     EXPECT_CALL(mockedUtils, setDbusProperty(dbusMapping, propertyValue))
259         .Times(2);
260     auto rc = platform_state_effecter::setStateEffecterStatesHandler<
261         MockdBusHandler, Handler>(mockedUtils, handler, 0x1, stateField);
262     ASSERT_EQ(rc, 0);
263 
264     pldm_pdr_destroy(inPDRRepo);
265     pldm_pdr_destroy(outPDRRepo);
266 }
267 
268 TEST(setStateEffecterStatesHandler, testBadRequest)
269 {
270     std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_GET_PDR_REQ_BYTES>
271         requestPayload{};
272     auto req = reinterpret_cast<pldm_msg*>(requestPayload.data());
273     size_t requestPayloadLength = requestPayload.size() - sizeof(pldm_msg_hdr);
274 
275     MockdBusHandler mockedUtils;
276     EXPECT_CALL(mockedUtils, getService(StrEq("/foo/bar"), _))
277         .Times(5)
278         .WillRepeatedly(Return("foo.bar"));
279 
280     auto inPDRRepo = pldm_pdr_init();
281     auto outPDRRepo = pldm_pdr_init();
282     Repo outRepo(outPDRRepo);
283     auto event = sdeventplus::Event::get_default();
284     Handler handler(&mockedUtils, "./pdr_jsons/state_effecter/good", inPDRRepo,
285                     nullptr, nullptr, nullptr, nullptr, event);
286     handler.getPDR(req, requestPayloadLength);
287     Repo inRepo(inPDRRepo);
288     getRepoByType(inRepo, outRepo, PLDM_STATE_EFFECTER_PDR);
289     pdr_utils::PdrEntry e;
290     auto record1 = pdr::getRecordByHandle(outRepo, 2, e);
291     ASSERT_NE(record1, nullptr);
292     pldm_state_effecter_pdr* pdr =
293         reinterpret_cast<pldm_state_effecter_pdr*>(e.data);
294     EXPECT_EQ(pdr->hdr.type, PLDM_STATE_EFFECTER_PDR);
295 
296     std::vector<set_effecter_state_field> stateField;
297     stateField.push_back({PLDM_REQUEST_SET, 3});
298     stateField.push_back({PLDM_REQUEST_SET, 4});
299 
300     auto rc = platform_state_effecter::setStateEffecterStatesHandler<
301         MockdBusHandler, Handler>(mockedUtils, handler, 0x1, stateField);
302     ASSERT_EQ(rc, PLDM_PLATFORM_SET_EFFECTER_UNSUPPORTED_SENSORSTATE);
303 
304     rc = platform_state_effecter::setStateEffecterStatesHandler<MockdBusHandler,
305                                                                 Handler>(
306         mockedUtils, handler, 0x9, stateField);
307     ASSERT_EQ(rc, PLDM_PLATFORM_INVALID_EFFECTER_ID);
308 
309     stateField.push_back({PLDM_REQUEST_SET, 4});
310     rc = platform_state_effecter::setStateEffecterStatesHandler<MockdBusHandler,
311                                                                 Handler>(
312         mockedUtils, handler, 0x1, stateField);
313     ASSERT_EQ(rc, PLDM_ERROR_INVALID_DATA);
314 
315     pldm_pdr_destroy(inPDRRepo);
316     pldm_pdr_destroy(outPDRRepo);
317 }
318 
319 TEST(setNumericEffecterValueHandler, testGoodRequest)
320 {
321     MockdBusHandler mockedUtils;
322     EXPECT_CALL(mockedUtils, getService(StrEq("/foo/bar"), _))
323         .Times(5)
324         .WillRepeatedly(Return("foo.bar"));
325 
326     auto inPDRRepo = pldm_pdr_init();
327     auto numericEffecterPdrRepo = pldm_pdr_init();
328     Repo numericEffecterPDRs(numericEffecterPdrRepo);
329     auto event = sdeventplus::Event::get_default();
330     Handler handler(&mockedUtils, "./pdr_jsons/state_effecter/good", inPDRRepo,
331                     nullptr, nullptr, nullptr, nullptr, event);
332     Repo inRepo(inPDRRepo);
333     getRepoByType(inRepo, numericEffecterPDRs, PLDM_NUMERIC_EFFECTER_PDR);
334 
335     pdr_utils::PdrEntry e;
336     auto record4 = pdr::getRecordByHandle(numericEffecterPDRs, 4, e);
337     ASSERT_NE(record4, nullptr);
338 
339     pldm_numeric_effecter_value_pdr* pdr =
340         reinterpret_cast<pldm_numeric_effecter_value_pdr*>(e.data);
341     EXPECT_EQ(pdr->hdr.type, PLDM_NUMERIC_EFFECTER_PDR);
342 
343     uint16_t effecterId = 3;
344     uint32_t effecterValue = 2100000000; // 2036-07-18 21:20:00
345     PropertyValue propertyValue = static_cast<uint64_t>(effecterValue);
346 
347     DBusMapping dbusMapping{"/foo/bar", "xyz.openbmc_project.Foo.Bar",
348                             "propertyName", "uint64_t"};
349     EXPECT_CALL(mockedUtils, setDbusProperty(dbusMapping, propertyValue))
350         .Times(1);
351 
352     auto rc = platform_numeric_effecter::setNumericEffecterValueHandler<
353         MockdBusHandler, Handler>(
354         mockedUtils, handler, effecterId, PLDM_EFFECTER_DATA_SIZE_UINT32,
355         reinterpret_cast<uint8_t*>(&effecterValue), 4);
356     ASSERT_EQ(rc, 0);
357 
358     pldm_pdr_destroy(inPDRRepo);
359     pldm_pdr_destroy(numericEffecterPdrRepo);
360 }
361 
362 TEST(setNumericEffecterValueHandler, testBadRequest)
363 {
364     MockdBusHandler mockedUtils;
365     EXPECT_CALL(mockedUtils, getService(StrEq("/foo/bar"), _))
366         .Times(5)
367         .WillRepeatedly(Return("foo.bar"));
368 
369     auto inPDRRepo = pldm_pdr_init();
370     auto numericEffecterPdrRepo = pldm_pdr_init();
371     Repo numericEffecterPDRs(numericEffecterPdrRepo);
372     auto event = sdeventplus::Event::get_default();
373     Handler handler(&mockedUtils, "./pdr_jsons/state_effecter/good", inPDRRepo,
374                     nullptr, nullptr, nullptr, nullptr, event);
375     Repo inRepo(inPDRRepo);
376     getRepoByType(inRepo, numericEffecterPDRs, PLDM_NUMERIC_EFFECTER_PDR);
377 
378     pdr_utils::PdrEntry e;
379     auto record4 = pdr::getRecordByHandle(numericEffecterPDRs, 4, e);
380     ASSERT_NE(record4, nullptr);
381 
382     pldm_numeric_effecter_value_pdr* pdr =
383         reinterpret_cast<pldm_numeric_effecter_value_pdr*>(e.data);
384     EXPECT_EQ(pdr->hdr.type, PLDM_NUMERIC_EFFECTER_PDR);
385 
386     uint16_t effecterId = 3;
387     uint64_t effecterValue = 9876543210;
388     auto rc = platform_numeric_effecter::setNumericEffecterValueHandler<
389         MockdBusHandler, Handler>(
390         mockedUtils, handler, effecterId, PLDM_EFFECTER_DATA_SIZE_SINT32,
391         reinterpret_cast<uint8_t*>(&effecterValue), 3);
392     ASSERT_EQ(rc, PLDM_ERROR_INVALID_DATA);
393 
394     pldm_pdr_destroy(inPDRRepo);
395     pldm_pdr_destroy(numericEffecterPdrRepo);
396 }
397 
398 TEST(parseStateSensor, allScenarios)
399 {
400     // Sample state sensor with SensorID - 1, EntityType - Processor Module(67)
401     // State Set ID - Operational Running Status(11), Supported States - 3,4
402     std::vector<uint8_t> sample1PDR{0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00,
403                                     0x00, 0x17, 0x00, 0x00, 0x00, 0x01, 0x00,
404                                     0x43, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
405                                     0x00, 0x01, 0x0b, 0x00, 0x01, 0x18};
406 
407     const auto& [terminusHandle1, sensorID1,
408                  sensorInfo1] = parseStateSensorPDR(sample1PDR);
409     const auto& [containerID1, entityType1,
410                  entityInstance1] = std::get<0>(sensorInfo1);
411     const auto& states1 = std::get<1>(sensorInfo1);
412     CompositeSensorStates statesCmp1{{3u, 4u}};
413 
414     ASSERT_EQ(le16toh(terminusHandle1), 0u);
415     ASSERT_EQ(le16toh(sensorID1), 1u);
416     ASSERT_EQ(le16toh(containerID1), 0u);
417     ASSERT_EQ(le16toh(entityType1), 67u);
418     ASSERT_EQ(le16toh(entityInstance1), 1u);
419     ASSERT_EQ(states1, statesCmp1);
420 
421     // Sample state sensor with SensorID - 2, EntityType - System Firmware(31)
422     // State Set ID - Availability(2), Supported States - 3,4,9,10,11,13
423     std::vector<uint8_t> sample2PDR{0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00,
424                                     0x00, 0x17, 0x00, 0x00, 0x00, 0x02, 0x00,
425                                     0x1F, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
426                                     0x00, 0x01, 0x02, 0x00, 0x02, 0x18, 0x2E};
427 
428     const auto& [terminusHandle2, sensorID2,
429                  sensorInfo2] = parseStateSensorPDR(sample2PDR);
430     const auto& [containerID2, entityType2,
431                  entityInstance2] = std::get<0>(sensorInfo2);
432     const auto& states2 = std::get<1>(sensorInfo2);
433     CompositeSensorStates statesCmp2{{3u, 4u, 9u, 10u, 11u, 13u}};
434 
435     ASSERT_EQ(le16toh(terminusHandle2), 0u);
436     ASSERT_EQ(le16toh(sensorID2), 2u);
437     ASSERT_EQ(le16toh(containerID2), 0u);
438     ASSERT_EQ(le16toh(entityType2), 31u);
439     ASSERT_EQ(le16toh(entityInstance2), 1u);
440     ASSERT_EQ(states2, statesCmp2);
441 
442     // Sample state sensor with SensorID - 3, EntityType - Virtual Machine
443     // Manager(33), Composite State Sensor -2 , State Set ID - Link State(33),
444     // Supported States - 1,2, State Set ID - Configuration State(15),
445     // Supported States - 1,2,3,4
446     std::vector<uint8_t> sample3PDR{
447         0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x17, 0x00, 0x00,
448         0x00, 0x03, 0x00, 0x21, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00,
449         0x02, 0x21, 0x00, 0x01, 0x06, 0x0F, 0x00, 0x01, 0x1E};
450 
451     const auto& [terminusHandle3, sensorID3,
452                  sensorInfo3] = parseStateSensorPDR(sample3PDR);
453     const auto& [containerID3, entityType3,
454                  entityInstance3] = std::get<0>(sensorInfo3);
455     const auto& states3 = std::get<1>(sensorInfo3);
456     CompositeSensorStates statesCmp3{{1u, 2u}, {1u, 2u, 3u, 4u}};
457 
458     ASSERT_EQ(le16toh(terminusHandle3), 0u);
459     ASSERT_EQ(le16toh(sensorID3), 3u);
460     ASSERT_EQ(le16toh(containerID3), 1u);
461     ASSERT_EQ(le16toh(entityType3), 33u);
462     ASSERT_EQ(le16toh(entityInstance3), 2u);
463     ASSERT_EQ(states3, statesCmp3);
464 }
465 
466 TEST(StateSensorHandler, allScenarios)
467 {
468     using namespace pldm::responder::events;
469 
470     StateSensorHandler handler{"./event_jsons/good"};
471     constexpr uint8_t eventState0 = 0;
472     constexpr uint8_t eventState1 = 1;
473     constexpr uint8_t eventState2 = 2;
474     constexpr uint8_t eventState3 = 3;
475 
476     // Event Entry 1
477     {
478         StateSensorEntry entry{1, 64, 1, 0};
479         const auto& [dbusMapping, eventStateMap] = handler.getEventInfo(entry);
480         DBusMapping mapping{"/xyz/abc/def",
481                             "xyz.openbmc_project.example1.value", "value1",
482                             "string"};
483         ASSERT_EQ(mapping == dbusMapping, true);
484 
485         const auto& propValue0 = eventStateMap.at(eventState0);
486         const auto& propValue1 = eventStateMap.at(eventState1);
487         const auto& propValue2 = eventStateMap.at(eventState2);
488         PropertyValue value0{std::in_place_type<std::string>,
489                              "xyz.openbmc_project.State.Normal"};
490         PropertyValue value1{std::in_place_type<std::string>,
491                              "xyz.openbmc_project.State.Critical"};
492         PropertyValue value2{std::in_place_type<std::string>,
493                              "xyz.openbmc_project.State.Fatal"};
494         ASSERT_EQ(value0 == propValue0, true);
495         ASSERT_EQ(value1 == propValue1, true);
496         ASSERT_EQ(value2 == propValue2, true);
497     }
498 
499     // Event Entry 2
500     {
501         StateSensorEntry entry{1, 64, 1, 1};
502         const auto& [dbusMapping, eventStateMap] = handler.getEventInfo(entry);
503         DBusMapping mapping{"/xyz/abc/def",
504                             "xyz.openbmc_project.example2.value", "value2",
505                             "uint8_t"};
506         ASSERT_EQ(mapping == dbusMapping, true);
507 
508         const auto& propValue0 = eventStateMap.at(eventState2);
509         const auto& propValue1 = eventStateMap.at(eventState3);
510         PropertyValue value0{std::in_place_type<uint8_t>, 9};
511         PropertyValue value1{std::in_place_type<uint8_t>, 10};
512         ASSERT_EQ(value0 == propValue0, true);
513         ASSERT_EQ(value1 == propValue1, true);
514     }
515 
516     // Event Entry 3
517     {
518         StateSensorEntry entry{2, 67, 2, 0};
519         const auto& [dbusMapping, eventStateMap] = handler.getEventInfo(entry);
520         DBusMapping mapping{"/xyz/abc/ghi",
521                             "xyz.openbmc_project.example3.value", "value3",
522                             "bool"};
523         ASSERT_EQ(mapping == dbusMapping, true);
524 
525         const auto& propValue0 = eventStateMap.at(eventState0);
526         const auto& propValue1 = eventStateMap.at(eventState1);
527         PropertyValue value0{std::in_place_type<bool>, false};
528         PropertyValue value1{std::in_place_type<bool>, true};
529         ASSERT_EQ(value0 == propValue0, true);
530         ASSERT_EQ(value1 == propValue1, true);
531     }
532 
533     // Invalid Entry
534     {
535         StateSensorEntry entry{0, 0, 0, 0};
536         ASSERT_THROW(handler.getEventInfo(entry), std::out_of_range);
537     }
538 }
539 
540 TEST(TerminusLocatorPDR, BMCTerminusLocatorPDR)
541 {
542     auto inPDRRepo = pldm_pdr_init();
543     auto outPDRRepo = pldm_pdr_init();
544     Repo outRepo(outPDRRepo);
545     MockdBusHandler mockedUtils;
546     auto event = sdeventplus::Event::get_default();
547     Handler handler(&mockedUtils, "", inPDRRepo, nullptr, nullptr, nullptr,
548                     nullptr, event);
549     Repo inRepo(inPDRRepo);
550     getRepoByType(inRepo, outRepo, PLDM_TERMINUS_LOCATOR_PDR);
551 
552     // 1 BMC terminus locator PDR in the PDR repository
553     ASSERT_EQ(outRepo.getRecordCount(), 1);
554 
555     pdr_utils::PdrEntry entry;
556     auto record = pdr::getRecordByHandle(outRepo, 1, entry);
557     ASSERT_NE(record, nullptr);
558 
559     auto pdr = reinterpret_cast<const pldm_terminus_locator_pdr*>(entry.data);
560     EXPECT_EQ(pdr->hdr.record_handle, 1);
561     EXPECT_EQ(pdr->hdr.version, 1);
562     EXPECT_EQ(pdr->hdr.type, PLDM_TERMINUS_LOCATOR_PDR);
563     EXPECT_EQ(pdr->hdr.record_change_num, 0);
564     EXPECT_EQ(pdr->hdr.length,
565               sizeof(pldm_terminus_locator_pdr) - sizeof(pldm_pdr_hdr));
566     EXPECT_EQ(pdr->terminus_handle, TERMINUS_HANDLE);
567     EXPECT_EQ(pdr->validity, PLDM_TL_PDR_VALID);
568     EXPECT_EQ(pdr->tid, TERMINUS_ID);
569     EXPECT_EQ(pdr->container_id, 0);
570     EXPECT_EQ(pdr->terminus_locator_type, PLDM_TERMINUS_LOCATOR_TYPE_MCTP_EID);
571     EXPECT_EQ(pdr->terminus_locator_value_size,
572               sizeof(pldm_terminus_locator_type_mctp_eid));
573     auto locatorValue =
574         reinterpret_cast<const pldm_terminus_locator_type_mctp_eid*>(
575             pdr->terminus_locator_value);
576     EXPECT_EQ(locatorValue->eid, BmcMctpEid);
577     pldm_pdr_destroy(inPDRRepo);
578     pldm_pdr_destroy(outPDRRepo);
579 }
580 
581 TEST(getStateSensorReadingsHandler, testGoodRequest)
582 {
583     MockdBusHandler mockedUtils;
584     EXPECT_CALL(mockedUtils, getService(StrEq("/foo/bar"), _))
585         .Times(1)
586         .WillRepeatedly(Return("foo.bar"));
587 
588     auto inPDRRepo = pldm_pdr_init();
589     auto outPDRRepo = pldm_pdr_init();
590     Repo outRepo(outPDRRepo);
591     auto event = sdeventplus::Event::get_default();
592     Handler handler(&mockedUtils, "./pdr_jsons/state_sensor/good", inPDRRepo,
593                     nullptr, nullptr, nullptr, nullptr, event);
594     Repo inRepo(inPDRRepo);
595     getRepoByType(inRepo, outRepo, PLDM_STATE_SENSOR_PDR);
596     pdr_utils::PdrEntry e;
597     auto record = pdr::getRecordByHandle(outRepo, 2, e);
598     ASSERT_NE(record, nullptr);
599     pldm_state_sensor_pdr* pdr =
600         reinterpret_cast<pldm_state_sensor_pdr*>(e.data);
601     EXPECT_EQ(pdr->hdr.type, PLDM_STATE_SENSOR_PDR);
602 
603     std::vector<get_sensor_state_field> stateField;
604     uint8_t compSensorCnt{};
605     uint8_t sensorRearmCnt = 1;
606 
607     MockdBusHandler handlerObj;
608     EXPECT_CALL(handlerObj,
609                 getDbusPropertyVariant(StrEq("/foo/bar"), StrEq("propertyName"),
610                                        StrEq("xyz.openbmc_project.Foo.Bar")))
611         .WillOnce(Return(
612             PropertyValue(std::string("xyz.openbmc_project.Foo.Bar.V0"))));
613 
614     auto rc = platform_state_sensor::getStateSensorReadingsHandler<
615         MockdBusHandler, Handler>(handlerObj, handler, 0x1, sensorRearmCnt,
616                                   compSensorCnt, stateField);
617     ASSERT_EQ(rc, 0);
618     ASSERT_EQ(compSensorCnt, 1);
619     ASSERT_EQ(stateField[0].sensor_op_state, PLDM_SENSOR_UNAVAILABLE);
620     ASSERT_EQ(stateField[0].present_state, PLDM_SENSOR_NORMAL);
621     ASSERT_EQ(stateField[0].previous_state, PLDM_SENSOR_UNKNOWN);
622     ASSERT_EQ(stateField[0].event_state, PLDM_SENSOR_UNKNOWN);
623 
624     pldm_pdr_destroy(inPDRRepo);
625     pldm_pdr_destroy(outPDRRepo);
626 }
627 
628 TEST(getStateSensorReadingsHandler, testBadRequest)
629 {
630     MockdBusHandler mockedUtils;
631     EXPECT_CALL(mockedUtils, getService(StrEq("/foo/bar"), _))
632         .Times(1)
633         .WillRepeatedly(Return("foo.bar"));
634 
635     auto inPDRRepo = pldm_pdr_init();
636     auto outPDRRepo = pldm_pdr_init();
637     Repo outRepo(outPDRRepo);
638     auto event = sdeventplus::Event::get_default();
639     Handler handler(&mockedUtils, "./pdr_jsons/state_sensor/good", inPDRRepo,
640                     nullptr, nullptr, nullptr, nullptr, event);
641     Repo inRepo(inPDRRepo);
642     getRepoByType(inRepo, outRepo, PLDM_STATE_SENSOR_PDR);
643     pdr_utils::PdrEntry e;
644     auto record = pdr::getRecordByHandle(outRepo, 2, e);
645     ASSERT_NE(record, nullptr);
646     pldm_state_sensor_pdr* pdr =
647         reinterpret_cast<pldm_state_sensor_pdr*>(e.data);
648     EXPECT_EQ(pdr->hdr.type, PLDM_STATE_SENSOR_PDR);
649 
650     std::vector<get_sensor_state_field> stateField;
651     uint8_t compSensorCnt{};
652     uint8_t sensorRearmCnt = 3;
653 
654     MockdBusHandler handlerObj;
655     auto rc = platform_state_sensor::getStateSensorReadingsHandler<
656         MockdBusHandler, Handler>(handlerObj, handler, 0x1, sensorRearmCnt,
657                                   compSensorCnt, stateField);
658     ASSERT_EQ(rc, PLDM_PLATFORM_REARM_UNAVAILABLE_IN_PRESENT_STATE);
659 
660     pldm_pdr_destroy(inPDRRepo);
661     pldm_pdr_destroy(outPDRRepo);
662 }
663