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