xref: /openbmc/pldm/libpldmresponder/test/libpldmresponder_platform_test.cpp (revision 146ff92b96198ce471a92ebbabf79bb79e9f6f8e)
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(getNumericEffecterValueHandler, testGoodRequest)
399 {
400     MockdBusHandler mockedUtils;
401     EXPECT_CALL(mockedUtils, getService(StrEq("/foo/bar"), _))
402         .Times(5)
403         .WillRepeatedly(Return("foo.bar"));
404 
405     auto inPDRRepo = pldm_pdr_init();
406     auto numericEffecterPdrRepo = pldm_pdr_init();
407     Repo numericEffecterPDRs(numericEffecterPdrRepo);
408     auto event = sdeventplus::Event::get_default();
409     Handler handler(&mockedUtils, "./pdr_jsons/state_effecter/good", inPDRRepo,
410                     nullptr, nullptr, nullptr, nullptr, event);
411     Repo inRepo(inPDRRepo);
412     getRepoByType(inRepo, numericEffecterPDRs, PLDM_NUMERIC_EFFECTER_PDR);
413 
414     pdr_utils::PdrEntry e;
415     auto record4 = pdr::getRecordByHandle(numericEffecterPDRs, 4, e);
416     ASSERT_NE(record4, nullptr);
417 
418     pldm_numeric_effecter_value_pdr* pdr =
419         reinterpret_cast<pldm_numeric_effecter_value_pdr*>(e.data);
420     EXPECT_EQ(pdr->hdr.type, PLDM_NUMERIC_EFFECTER_PDR);
421 
422     uint16_t effecterId = 3;
423 
424     uint8_t effecterDataSize{};
425     pldm::utils::PropertyValue dbusValue;
426     std::string propertyType;
427 
428     // effecterValue return the present numeric setting
429     uint32_t effecterValue = 2100000000;
430     using effecterOperationalState = uint8_t;
431     using completionCode = uint8_t;
432 
433     EXPECT_CALL(mockedUtils,
434                 getDbusPropertyVariant(StrEq("/foo/bar"), StrEq("propertyName"),
435                                        StrEq("xyz.openbmc_project.Foo.Bar")))
436         .WillOnce(Return(PropertyValue(static_cast<uint64_t>(effecterValue))));
437 
438     auto rc = platform_numeric_effecter::getNumericEffecterData<MockdBusHandler,
439                                                                 Handler>(
440         mockedUtils, handler, effecterId, effecterDataSize, propertyType,
441         dbusValue);
442 
443     ASSERT_EQ(rc, 0);
444 
445     size_t responsePayloadLength = sizeof(completionCode) +
446                                    sizeof(effecterDataSize) +
447                                    sizeof(effecterOperationalState) +
448                                    getEffecterDataSize(effecterDataSize) +
449                                    getEffecterDataSize(effecterDataSize);
450 
451     Response response(responsePayloadLength + sizeof(pldm_msg_hdr));
452     auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
453 
454     rc = platform_numeric_effecter::getNumericEffecterValueHandler(
455         propertyType, dbusValue, effecterDataSize, responsePtr,
456         responsePayloadLength, 1);
457 
458     ASSERT_EQ(rc, 0);
459 
460     struct pldm_get_numeric_effecter_value_resp* resp =
461         reinterpret_cast<struct pldm_get_numeric_effecter_value_resp*>(
462             responsePtr->payload);
463     ASSERT_EQ(PLDM_SUCCESS, resp->completion_code);
464     uint32_t valPresent;
465     memcpy(&valPresent, &resp->pending_and_present_values[4],
466            sizeof(valPresent));
467 
468     ASSERT_EQ(effecterValue, valPresent);
469 
470     pldm_pdr_destroy(inPDRRepo);
471     pldm_pdr_destroy(numericEffecterPdrRepo);
472 }
473 
474 TEST(getNumericEffecterValueHandler, testBadRequest)
475 {
476     MockdBusHandler mockedUtils;
477     EXPECT_CALL(mockedUtils, getService(StrEq("/foo/bar"), _))
478         .Times(5)
479         .WillRepeatedly(Return("foo.bar"));
480 
481     auto inPDRRepo = pldm_pdr_init();
482     auto numericEffecterPdrRepo = pldm_pdr_init();
483     Repo numericEffecterPDRs(numericEffecterPdrRepo);
484     auto event = sdeventplus::Event::get_default();
485     Handler handler(&mockedUtils, "./pdr_jsons/state_effecter/good", inPDRRepo,
486                     nullptr, nullptr, nullptr, nullptr, event);
487     Repo inRepo(inPDRRepo);
488     getRepoByType(inRepo, numericEffecterPDRs, PLDM_NUMERIC_EFFECTER_PDR);
489 
490     pdr_utils::PdrEntry e;
491     auto record4 = pdr::getRecordByHandle(numericEffecterPDRs, 4, e);
492     ASSERT_NE(record4, nullptr);
493 
494     pldm_numeric_effecter_value_pdr* pdr =
495         reinterpret_cast<pldm_numeric_effecter_value_pdr*>(e.data);
496     EXPECT_EQ(pdr->hdr.type, PLDM_NUMERIC_EFFECTER_PDR);
497 
498     uint16_t effecterId = 4;
499 
500     uint8_t effecterDataSize{};
501     pldm::utils::PropertyValue dbusValue;
502     std::string propertyType;
503 
504     auto rc = platform_numeric_effecter::getNumericEffecterData<MockdBusHandler,
505                                                                 Handler>(
506         mockedUtils, handler, effecterId, effecterDataSize, propertyType,
507         dbusValue);
508 
509     ASSERT_EQ(rc, 128);
510 
511     pldm_pdr_destroy(inPDRRepo);
512     pldm_pdr_destroy(numericEffecterPdrRepo);
513 }
514 
515 TEST(parseStateSensor, allScenarios)
516 {
517     // Sample state sensor with SensorID - 1, EntityType - Processor Module(67)
518     // State Set ID - Operational Running Status(11), Supported States - 3,4
519     std::vector<uint8_t> sample1PDR{0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00,
520                                     0x00, 0x17, 0x00, 0x00, 0x00, 0x01, 0x00,
521                                     0x43, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
522                                     0x00, 0x01, 0x0b, 0x00, 0x01, 0x18};
523 
524     const auto& [terminusHandle1, sensorID1,
525                  sensorInfo1] = parseStateSensorPDR(sample1PDR);
526     const auto& [containerID1, entityType1,
527                  entityInstance1] = std::get<0>(sensorInfo1);
528     const auto& states1 = std::get<1>(sensorInfo1);
529     CompositeSensorStates statesCmp1{{3u, 4u}};
530 
531     ASSERT_EQ(le16toh(terminusHandle1), 0u);
532     ASSERT_EQ(le16toh(sensorID1), 1u);
533     ASSERT_EQ(le16toh(containerID1), 0u);
534     ASSERT_EQ(le16toh(entityType1), 67u);
535     ASSERT_EQ(le16toh(entityInstance1), 1u);
536     ASSERT_EQ(states1, statesCmp1);
537 
538     // Sample state sensor with SensorID - 2, EntityType - System Firmware(31)
539     // State Set ID - Availability(2), Supported States - 3,4,9,10,11,13
540     std::vector<uint8_t> sample2PDR{0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00,
541                                     0x00, 0x17, 0x00, 0x00, 0x00, 0x02, 0x00,
542                                     0x1F, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
543                                     0x00, 0x01, 0x02, 0x00, 0x02, 0x18, 0x2E};
544 
545     const auto& [terminusHandle2, sensorID2,
546                  sensorInfo2] = parseStateSensorPDR(sample2PDR);
547     const auto& [containerID2, entityType2,
548                  entityInstance2] = std::get<0>(sensorInfo2);
549     const auto& states2 = std::get<1>(sensorInfo2);
550     CompositeSensorStates statesCmp2{{3u, 4u, 9u, 10u, 11u, 13u}};
551 
552     ASSERT_EQ(le16toh(terminusHandle2), 0u);
553     ASSERT_EQ(le16toh(sensorID2), 2u);
554     ASSERT_EQ(le16toh(containerID2), 0u);
555     ASSERT_EQ(le16toh(entityType2), 31u);
556     ASSERT_EQ(le16toh(entityInstance2), 1u);
557     ASSERT_EQ(states2, statesCmp2);
558 
559     // Sample state sensor with SensorID - 3, EntityType - Virtual Machine
560     // Manager(33), Composite State Sensor -2 , State Set ID - Link State(33),
561     // Supported States - 1,2, State Set ID - Configuration State(15),
562     // Supported States - 1,2,3,4
563     std::vector<uint8_t> sample3PDR{
564         0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x17, 0x00, 0x00,
565         0x00, 0x03, 0x00, 0x21, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00,
566         0x02, 0x21, 0x00, 0x01, 0x06, 0x0F, 0x00, 0x01, 0x1E};
567 
568     const auto& [terminusHandle3, sensorID3,
569                  sensorInfo3] = parseStateSensorPDR(sample3PDR);
570     const auto& [containerID3, entityType3,
571                  entityInstance3] = std::get<0>(sensorInfo3);
572     const auto& states3 = std::get<1>(sensorInfo3);
573     CompositeSensorStates statesCmp3{{1u, 2u}, {1u, 2u, 3u, 4u}};
574 
575     ASSERT_EQ(le16toh(terminusHandle3), 0u);
576     ASSERT_EQ(le16toh(sensorID3), 3u);
577     ASSERT_EQ(le16toh(containerID3), 1u);
578     ASSERT_EQ(le16toh(entityType3), 33u);
579     ASSERT_EQ(le16toh(entityInstance3), 2u);
580     ASSERT_EQ(states3, statesCmp3);
581 }
582 
583 TEST(StateSensorHandler, allScenarios)
584 {
585     using namespace pldm::responder::events;
586 
587     StateSensorHandler handler{"./event_jsons/good"};
588     constexpr uint8_t eventState0 = 0;
589     constexpr uint8_t eventState1 = 1;
590     constexpr uint8_t eventState2 = 2;
591     constexpr uint8_t eventState3 = 3;
592 
593     // Event Entry 1
594     {
595         StateSensorEntry entry{1, 64, 1, 0};
596         const auto& [dbusMapping, eventStateMap] = handler.getEventInfo(entry);
597         DBusMapping mapping{"/xyz/abc/def",
598                             "xyz.openbmc_project.example1.value", "value1",
599                             "string"};
600         ASSERT_EQ(mapping == dbusMapping, true);
601 
602         const auto& propValue0 = eventStateMap.at(eventState0);
603         const auto& propValue1 = eventStateMap.at(eventState1);
604         const auto& propValue2 = eventStateMap.at(eventState2);
605         PropertyValue value0{std::in_place_type<std::string>,
606                              "xyz.openbmc_project.State.Normal"};
607         PropertyValue value1{std::in_place_type<std::string>,
608                              "xyz.openbmc_project.State.Critical"};
609         PropertyValue value2{std::in_place_type<std::string>,
610                              "xyz.openbmc_project.State.Fatal"};
611         ASSERT_EQ(value0 == propValue0, true);
612         ASSERT_EQ(value1 == propValue1, true);
613         ASSERT_EQ(value2 == propValue2, true);
614     }
615 
616     // Event Entry 2
617     {
618         StateSensorEntry entry{1, 64, 1, 1};
619         const auto& [dbusMapping, eventStateMap] = handler.getEventInfo(entry);
620         DBusMapping mapping{"/xyz/abc/def",
621                             "xyz.openbmc_project.example2.value", "value2",
622                             "uint8_t"};
623         ASSERT_EQ(mapping == dbusMapping, true);
624 
625         const auto& propValue0 = eventStateMap.at(eventState2);
626         const auto& propValue1 = eventStateMap.at(eventState3);
627         PropertyValue value0{std::in_place_type<uint8_t>, 9};
628         PropertyValue value1{std::in_place_type<uint8_t>, 10};
629         ASSERT_EQ(value0 == propValue0, true);
630         ASSERT_EQ(value1 == propValue1, true);
631     }
632 
633     // Event Entry 3
634     {
635         StateSensorEntry entry{2, 67, 2, 0};
636         const auto& [dbusMapping, eventStateMap] = handler.getEventInfo(entry);
637         DBusMapping mapping{"/xyz/abc/ghi",
638                             "xyz.openbmc_project.example3.value", "value3",
639                             "bool"};
640         ASSERT_EQ(mapping == dbusMapping, true);
641 
642         const auto& propValue0 = eventStateMap.at(eventState0);
643         const auto& propValue1 = eventStateMap.at(eventState1);
644         PropertyValue value0{std::in_place_type<bool>, false};
645         PropertyValue value1{std::in_place_type<bool>, true};
646         ASSERT_EQ(value0 == propValue0, true);
647         ASSERT_EQ(value1 == propValue1, true);
648     }
649 
650     // Invalid Entry
651     {
652         StateSensorEntry entry{0, 0, 0, 0};
653         ASSERT_THROW(handler.getEventInfo(entry), std::out_of_range);
654     }
655 }
656 
657 TEST(TerminusLocatorPDR, BMCTerminusLocatorPDR)
658 {
659     auto inPDRRepo = pldm_pdr_init();
660     auto outPDRRepo = pldm_pdr_init();
661     Repo outRepo(outPDRRepo);
662     MockdBusHandler mockedUtils;
663     auto event = sdeventplus::Event::get_default();
664     Handler handler(&mockedUtils, "", inPDRRepo, nullptr, nullptr, nullptr,
665                     nullptr, event);
666     Repo inRepo(inPDRRepo);
667     getRepoByType(inRepo, outRepo, PLDM_TERMINUS_LOCATOR_PDR);
668 
669     // 1 BMC terminus locator PDR in the PDR repository
670     ASSERT_EQ(outRepo.getRecordCount(), 1);
671 
672     pdr_utils::PdrEntry entry;
673     auto record = pdr::getRecordByHandle(outRepo, 1, entry);
674     ASSERT_NE(record, nullptr);
675 
676     auto pdr = reinterpret_cast<const pldm_terminus_locator_pdr*>(entry.data);
677     EXPECT_EQ(pdr->hdr.record_handle, 1);
678     EXPECT_EQ(pdr->hdr.version, 1);
679     EXPECT_EQ(pdr->hdr.type, PLDM_TERMINUS_LOCATOR_PDR);
680     EXPECT_EQ(pdr->hdr.record_change_num, 0);
681     EXPECT_EQ(pdr->hdr.length,
682               sizeof(pldm_terminus_locator_pdr) - sizeof(pldm_pdr_hdr));
683     EXPECT_EQ(pdr->terminus_handle, TERMINUS_HANDLE);
684     EXPECT_EQ(pdr->validity, PLDM_TL_PDR_VALID);
685     EXPECT_EQ(pdr->tid, TERMINUS_ID);
686     EXPECT_EQ(pdr->container_id, 0);
687     EXPECT_EQ(pdr->terminus_locator_type, PLDM_TERMINUS_LOCATOR_TYPE_MCTP_EID);
688     EXPECT_EQ(pdr->terminus_locator_value_size,
689               sizeof(pldm_terminus_locator_type_mctp_eid));
690     auto locatorValue =
691         reinterpret_cast<const pldm_terminus_locator_type_mctp_eid*>(
692             pdr->terminus_locator_value);
693     EXPECT_EQ(locatorValue->eid, BmcMctpEid);
694     pldm_pdr_destroy(inPDRRepo);
695     pldm_pdr_destroy(outPDRRepo);
696 }
697 
698 TEST(getStateSensorReadingsHandler, testGoodRequest)
699 {
700     MockdBusHandler mockedUtils;
701     EXPECT_CALL(mockedUtils, getService(StrEq("/foo/bar"), _))
702         .Times(1)
703         .WillRepeatedly(Return("foo.bar"));
704 
705     auto inPDRRepo = pldm_pdr_init();
706     auto outPDRRepo = pldm_pdr_init();
707     Repo outRepo(outPDRRepo);
708     auto event = sdeventplus::Event::get_default();
709     Handler handler(&mockedUtils, "./pdr_jsons/state_sensor/good", inPDRRepo,
710                     nullptr, nullptr, nullptr, nullptr, event);
711     Repo inRepo(inPDRRepo);
712     getRepoByType(inRepo, outRepo, PLDM_STATE_SENSOR_PDR);
713     pdr_utils::PdrEntry e;
714     auto record = pdr::getRecordByHandle(outRepo, 2, e);
715     ASSERT_NE(record, nullptr);
716     pldm_state_sensor_pdr* pdr =
717         reinterpret_cast<pldm_state_sensor_pdr*>(e.data);
718     EXPECT_EQ(pdr->hdr.type, PLDM_STATE_SENSOR_PDR);
719 
720     std::vector<get_sensor_state_field> stateField;
721     uint8_t compSensorCnt{};
722     uint8_t sensorRearmCnt = 1;
723 
724     MockdBusHandler handlerObj;
725     EXPECT_CALL(handlerObj,
726                 getDbusPropertyVariant(StrEq("/foo/bar"), StrEq("propertyName"),
727                                        StrEq("xyz.openbmc_project.Foo.Bar")))
728         .WillOnce(Return(
729             PropertyValue(std::string("xyz.openbmc_project.Foo.Bar.V0"))));
730 
731     auto rc = platform_state_sensor::getStateSensorReadingsHandler<
732         MockdBusHandler, Handler>(handlerObj, handler, 0x1, sensorRearmCnt,
733                                   compSensorCnt, stateField);
734     ASSERT_EQ(rc, 0);
735     ASSERT_EQ(compSensorCnt, 1);
736     ASSERT_EQ(stateField[0].sensor_op_state, PLDM_SENSOR_UNAVAILABLE);
737     ASSERT_EQ(stateField[0].present_state, PLDM_SENSOR_NORMAL);
738     ASSERT_EQ(stateField[0].previous_state, PLDM_SENSOR_UNKNOWN);
739     ASSERT_EQ(stateField[0].event_state, PLDM_SENSOR_UNKNOWN);
740 
741     pldm_pdr_destroy(inPDRRepo);
742     pldm_pdr_destroy(outPDRRepo);
743 }
744 
745 TEST(getStateSensorReadingsHandler, testBadRequest)
746 {
747     MockdBusHandler mockedUtils;
748     EXPECT_CALL(mockedUtils, getService(StrEq("/foo/bar"), _))
749         .Times(1)
750         .WillRepeatedly(Return("foo.bar"));
751 
752     auto inPDRRepo = pldm_pdr_init();
753     auto outPDRRepo = pldm_pdr_init();
754     Repo outRepo(outPDRRepo);
755     auto event = sdeventplus::Event::get_default();
756     Handler handler(&mockedUtils, "./pdr_jsons/state_sensor/good", inPDRRepo,
757                     nullptr, nullptr, nullptr, nullptr, event);
758     Repo inRepo(inPDRRepo);
759     getRepoByType(inRepo, outRepo, PLDM_STATE_SENSOR_PDR);
760     pdr_utils::PdrEntry e;
761     auto record = pdr::getRecordByHandle(outRepo, 2, e);
762     ASSERT_NE(record, nullptr);
763     pldm_state_sensor_pdr* pdr =
764         reinterpret_cast<pldm_state_sensor_pdr*>(e.data);
765     EXPECT_EQ(pdr->hdr.type, PLDM_STATE_SENSOR_PDR);
766 
767     std::vector<get_sensor_state_field> stateField;
768     uint8_t compSensorCnt{};
769     uint8_t sensorRearmCnt = 3;
770 
771     MockdBusHandler handlerObj;
772     auto rc = platform_state_sensor::getStateSensorReadingsHandler<
773         MockdBusHandler, Handler>(handlerObj, handler, 0x1, sensorRearmCnt,
774                                   compSensorCnt, stateField);
775     ASSERT_EQ(rc, PLDM_PLATFORM_REARM_UNAVAILABLE_IN_PRESENT_STATE);
776 
777     pldm_pdr_destroy(inPDRRepo);
778     pldm_pdr_destroy(outPDRRepo);
779 }
780