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                     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                     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                     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                     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                     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                     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                     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                     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                     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                     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                     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, false};
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, false};
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, false};
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, false};
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     // Event Entry 5
681     {
682         StateSensorEntry entry{0xFFFF, 120, 2, 0, 2, true};
683         const auto& [dbusMapping, eventStateMap] = handler.getEventInfo(entry);
684         DBusMapping mapping{"/xyz/abc/mno",
685                             "xyz.openbmc_project.example5.value", "value5",
686                             "string"};
687         ASSERT_EQ(mapping == dbusMapping, true);
688 
689         const auto& propValue0 = eventStateMap.at(eventState0);
690         const auto& propValue1 = eventStateMap.at(eventState1);
691         const auto& propValue2 = eventStateMap.at(eventState2);
692         PropertyValue value0{std::in_place_type<std::string>, "Enabled"};
693         PropertyValue value1{std::in_place_type<std::string>, "Disabled"};
694         PropertyValue value2{std::in_place_type<std::string>, "Auto"};
695         ASSERT_EQ(value0 == propValue0, true);
696         ASSERT_EQ(value1 == propValue1, true);
697         ASSERT_EQ(value2 == propValue2, true);
698     }
699     // Event Entry 6
700     {
701         StateSensorEntry entry{10, 120, 2, 0, 2, true};
702         const auto& [dbusMapping, eventStateMap] = handler.getEventInfo(entry);
703         DBusMapping mapping{"/xyz/abc/opk",
704                             "xyz.openbmc_project.example6.value", "value6",
705                             "string"};
706         ASSERT_EQ(mapping == dbusMapping, true);
707 
708         const auto& propValue0 = eventStateMap.at(eventState0);
709         const auto& propValue1 = eventStateMap.at(eventState1);
710         const auto& propValue2 = eventStateMap.at(eventState2);
711         PropertyValue value0{std::in_place_type<std::string>, "Enabled"};
712         PropertyValue value1{std::in_place_type<std::string>, "Disabled"};
713         PropertyValue value2{std::in_place_type<std::string>, "Auto"};
714         ASSERT_EQ(value0 == propValue0, true);
715         ASSERT_EQ(value1 == propValue1, true);
716         ASSERT_EQ(value2 == propValue2, true);
717     }
718     // Event Entry 7
719     {
720         StateSensorEntry entry{10, 120, 2, 0, 2, false};
721         const auto& [dbusMapping, eventStateMap] = handler.getEventInfo(entry);
722         DBusMapping mapping{"/xyz/abc/opk",
723                             "xyz.openbmc_project.example6.value", "value6",
724                             "string"};
725         ASSERT_EQ(mapping == dbusMapping, true);
726 
727         const auto& propValue0 = eventStateMap.at(eventState0);
728         const auto& propValue1 = eventStateMap.at(eventState1);
729         const auto& propValue2 = eventStateMap.at(eventState2);
730         PropertyValue value0{std::in_place_type<std::string>, "Enabled"};
731         PropertyValue value1{std::in_place_type<std::string>, "Disabled"};
732         PropertyValue value2{std::in_place_type<std::string>, "Auto"};
733         ASSERT_EQ(value0 == propValue0, true);
734         ASSERT_EQ(value1 == propValue1, true);
735         ASSERT_EQ(value2 == propValue2, true);
736     }
737 
738     // Invalid Entry
739     {
740         StateSensorEntry entry{0, 0, 0, 0, 1, false};
741         ASSERT_THROW(handler.getEventInfo(entry), std::out_of_range);
742     }
743 }
744 
745 TEST(TerminusLocatorPDR, BMCTerminusLocatorPDR)
746 {
747     auto inPDRRepo = pldm_pdr_init();
748     auto outPDRRepo = pldm_pdr_init();
749     Repo outRepo(outPDRRepo);
750     MockdBusHandler mockedUtils;
751     auto event = sdeventplus::Event::get_default();
752     Handler handler(&mockedUtils, 0, nullptr, "", inPDRRepo, nullptr, nullptr,
753                     nullptr, nullptr, nullptr, event);
754     Repo inRepo(inPDRRepo);
755     getRepoByType(inRepo, outRepo, PLDM_TERMINUS_LOCATOR_PDR);
756 
757     // 1 BMC terminus locator PDR in the PDR repository
758     ASSERT_EQ(outRepo.getRecordCount(), 1);
759 
760     pdr_utils::PdrEntry entry;
761     auto record = pdr::getRecordByHandle(outRepo, 1, entry);
762     ASSERT_NE(record, nullptr);
763 
764     auto pdr = reinterpret_cast<const pldm_terminus_locator_pdr*>(entry.data);
765     EXPECT_EQ(pdr->hdr.record_handle, 1);
766     EXPECT_EQ(pdr->hdr.version, 1);
767     EXPECT_EQ(pdr->hdr.type, PLDM_TERMINUS_LOCATOR_PDR);
768     EXPECT_EQ(pdr->hdr.record_change_num, 0);
769     EXPECT_EQ(pdr->hdr.length,
770               sizeof(pldm_terminus_locator_pdr) - sizeof(pldm_pdr_hdr));
771     EXPECT_EQ(pdr->terminus_handle, TERMINUS_HANDLE);
772     EXPECT_EQ(pdr->validity, PLDM_TL_PDR_VALID);
773     EXPECT_EQ(pdr->tid, TERMINUS_ID);
774     EXPECT_EQ(pdr->container_id, 0);
775     EXPECT_EQ(pdr->terminus_locator_type, PLDM_TERMINUS_LOCATOR_TYPE_MCTP_EID);
776     EXPECT_EQ(pdr->terminus_locator_value_size,
777               sizeof(pldm_terminus_locator_type_mctp_eid));
778     auto locatorValue =
779         reinterpret_cast<const pldm_terminus_locator_type_mctp_eid*>(
780             pdr->terminus_locator_value);
781     EXPECT_EQ(locatorValue->eid, BmcMctpEid);
782     pldm_pdr_destroy(inPDRRepo);
783     pldm_pdr_destroy(outPDRRepo);
784 }
785 
786 TEST(getStateSensorReadingsHandler, testGoodRequest)
787 {
788     MockdBusHandler mockedUtils;
789     EXPECT_CALL(mockedUtils, getService(StrEq("/foo/bar"), _))
790         .Times(1)
791         .WillRepeatedly(Return("foo.bar"));
792 
793     auto inPDRRepo = pldm_pdr_init();
794     auto outPDRRepo = pldm_pdr_init();
795     Repo outRepo(outPDRRepo);
796     auto event = sdeventplus::Event::get_default();
797     Handler handler(&mockedUtils, 0, nullptr, "./pdr_jsons/state_sensor/good",
798                     inPDRRepo, nullptr, nullptr, nullptr, nullptr, nullptr,
799                     event);
800     Repo inRepo(inPDRRepo);
801     getRepoByType(inRepo, outRepo, PLDM_STATE_SENSOR_PDR);
802     pdr_utils::PdrEntry e;
803     auto record = pdr::getRecordByHandle(outRepo, 2, e);
804     ASSERT_NE(record, nullptr);
805     pldm_state_sensor_pdr* pdr =
806         reinterpret_cast<pldm_state_sensor_pdr*>(e.data);
807     EXPECT_EQ(pdr->hdr.type, PLDM_STATE_SENSOR_PDR);
808 
809     std::vector<get_sensor_state_field> stateField;
810     uint8_t compSensorCnt{};
811     uint8_t sensorRearmCnt = 1;
812 
813     MockdBusHandler handlerObj;
814     EXPECT_CALL(handlerObj,
815                 getDbusPropertyVariant(StrEq("/foo/bar"), StrEq("propertyName"),
816                                        StrEq("xyz.openbmc_project.Foo.Bar")))
817         .WillOnce(Return(
818             PropertyValue(std::string("xyz.openbmc_project.Foo.Bar.V0"))));
819     EventStates cache = {PLDM_SENSOR_NORMAL};
820     pldm::stateSensorCacheMaps sensorCache;
821     sensorCache.emplace(0x1, cache);
822     auto rc = platform_state_sensor::getStateSensorReadingsHandler<
823         MockdBusHandler, Handler>(handlerObj, handler, 0x1, sensorRearmCnt,
824                                   compSensorCnt, stateField, sensorCache);
825     ASSERT_EQ(rc, 0);
826     ASSERT_EQ(compSensorCnt, 1);
827     ASSERT_EQ(stateField[0].sensor_op_state, PLDM_SENSOR_UNAVAILABLE);
828     ASSERT_EQ(stateField[0].present_state, PLDM_SENSOR_NORMAL);
829     ASSERT_EQ(stateField[0].previous_state, PLDM_SENSOR_NORMAL);
830     ASSERT_EQ(stateField[0].event_state, PLDM_SENSOR_UNKNOWN);
831 
832     pldm_pdr_destroy(inPDRRepo);
833     pldm_pdr_destroy(outPDRRepo);
834 }
835 
836 TEST(getStateSensorReadingsHandler, testBadRequest)
837 {
838     MockdBusHandler mockedUtils;
839     EXPECT_CALL(mockedUtils, getService(StrEq("/foo/bar"), _))
840         .Times(1)
841         .WillRepeatedly(Return("foo.bar"));
842 
843     auto inPDRRepo = pldm_pdr_init();
844     auto outPDRRepo = pldm_pdr_init();
845     Repo outRepo(outPDRRepo);
846     auto event = sdeventplus::Event::get_default();
847     Handler handler(&mockedUtils, 0, nullptr, "./pdr_jsons/state_sensor/good",
848                     inPDRRepo, nullptr, nullptr, nullptr, nullptr, nullptr,
849                     event);
850     Repo inRepo(inPDRRepo);
851     getRepoByType(inRepo, outRepo, PLDM_STATE_SENSOR_PDR);
852     pdr_utils::PdrEntry e;
853     auto record = pdr::getRecordByHandle(outRepo, 2, e);
854     ASSERT_NE(record, nullptr);
855     pldm_state_sensor_pdr* pdr =
856         reinterpret_cast<pldm_state_sensor_pdr*>(e.data);
857     EXPECT_EQ(pdr->hdr.type, PLDM_STATE_SENSOR_PDR);
858 
859     std::vector<get_sensor_state_field> stateField;
860     uint8_t compSensorCnt{};
861     uint8_t sensorRearmCnt = 3;
862 
863     MockdBusHandler handlerObj;
864     EventStates cache = {PLDM_SENSOR_NORMAL};
865     pldm::stateSensorCacheMaps sensorCache;
866     sensorCache.emplace(0x1, cache);
867     auto rc = platform_state_sensor::getStateSensorReadingsHandler<
868         MockdBusHandler, Handler>(handlerObj, handler, 0x1, sensorRearmCnt,
869                                   compSensorCnt, stateField, sensorCache);
870     ASSERT_EQ(rc, PLDM_PLATFORM_REARM_UNAVAILABLE_IN_PRESENT_STATE);
871 
872     pldm_pdr_destroy(inPDRRepo);
873     pldm_pdr_destroy(outPDRRepo);
874 }
875