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