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<
311         MockdBusHandler, Handler>(mockedUtils, handler, 0x9, stateField);
312     ASSERT_EQ(rc, PLDM_PLATFORM_INVALID_EFFECTER_ID);
313 
314     stateField.push_back({PLDM_REQUEST_SET, 4});
315     rc = platform_state_effecter::setStateEffecterStatesHandler<
316         MockdBusHandler, Handler>(mockedUtils, handler, 0x1, stateField);
317     ASSERT_EQ(rc, PLDM_ERROR_INVALID_DATA);
318 
319     pldm_pdr_destroy(inPDRRepo);
320     pldm_pdr_destroy(outPDRRepo);
321 }
322 
323 TEST(setNumericEffecterValueHandler, testGoodRequest)
324 {
325     MockdBusHandler mockedUtils;
326     EXPECT_CALL(mockedUtils, getService(StrEq("/foo/bar"), _))
327         .Times(5)
328         .WillRepeatedly(Return("foo.bar"));
329 
330     auto inPDRRepo = pldm_pdr_init();
331     auto numericEffecterPdrRepo = pldm_pdr_init();
332     Repo numericEffecterPDRs(numericEffecterPdrRepo);
333     auto event = sdeventplus::Event::get_default();
334     Handler handler(&mockedUtils, 0, nullptr, "./pdr_jsons/state_effecter/good",
335                     inPDRRepo, nullptr, nullptr, nullptr, nullptr, nullptr,
336                     event);
337     Repo inRepo(inPDRRepo);
338     getRepoByType(inRepo, numericEffecterPDRs, PLDM_NUMERIC_EFFECTER_PDR);
339 
340     pdr_utils::PdrEntry e;
341     auto record4 = pdr::getRecordByHandle(numericEffecterPDRs, 4, e);
342     ASSERT_NE(record4, nullptr);
343 
344     pldm_numeric_effecter_value_pdr* pdr =
345         reinterpret_cast<pldm_numeric_effecter_value_pdr*>(e.data);
346     EXPECT_EQ(pdr->hdr.type, PLDM_NUMERIC_EFFECTER_PDR);
347 
348     uint16_t effecterId = 3;
349     uint32_t effecterValue = 2100000000; // 2036-07-18 21:20:00
350     PropertyValue propertyValue = static_cast<uint64_t>(effecterValue);
351 
352     DBusMapping dbusMapping{"/foo/bar", "xyz.openbmc_project.Foo.Bar",
353                             "propertyName", "uint64_t"};
354     EXPECT_CALL(mockedUtils, setDbusProperty(dbusMapping, propertyValue))
355         .Times(1);
356 
357     auto rc = platform_numeric_effecter::setNumericEffecterValueHandler<
358         MockdBusHandler, Handler>(
359         mockedUtils, handler, effecterId, PLDM_EFFECTER_DATA_SIZE_UINT32,
360         reinterpret_cast<uint8_t*>(&effecterValue), 4);
361     ASSERT_EQ(rc, 0);
362 
363     pldm_pdr_destroy(inPDRRepo);
364     pldm_pdr_destroy(numericEffecterPdrRepo);
365 }
366 
367 TEST(setNumericEffecterValueHandler, testBadRequest)
368 {
369     MockdBusHandler mockedUtils;
370     EXPECT_CALL(mockedUtils, getService(StrEq("/foo/bar"), _))
371         .Times(5)
372         .WillRepeatedly(Return("foo.bar"));
373 
374     auto inPDRRepo = pldm_pdr_init();
375     auto numericEffecterPdrRepo = pldm_pdr_init();
376     Repo numericEffecterPDRs(numericEffecterPdrRepo);
377     auto event = sdeventplus::Event::get_default();
378     Handler handler(&mockedUtils, 0, nullptr, "./pdr_jsons/state_effecter/good",
379                     inPDRRepo, nullptr, nullptr, nullptr, nullptr, nullptr,
380                     event);
381     Repo inRepo(inPDRRepo);
382     getRepoByType(inRepo, numericEffecterPDRs, PLDM_NUMERIC_EFFECTER_PDR);
383 
384     pdr_utils::PdrEntry e;
385     auto record4 = pdr::getRecordByHandle(numericEffecterPDRs, 4, e);
386     ASSERT_NE(record4, nullptr);
387 
388     pldm_numeric_effecter_value_pdr* pdr =
389         reinterpret_cast<pldm_numeric_effecter_value_pdr*>(e.data);
390     EXPECT_EQ(pdr->hdr.type, PLDM_NUMERIC_EFFECTER_PDR);
391 
392     uint16_t effecterId = 3;
393     uint64_t effecterValue = 9876543210;
394     auto rc = platform_numeric_effecter::setNumericEffecterValueHandler<
395         MockdBusHandler, Handler>(
396         mockedUtils, handler, effecterId, PLDM_EFFECTER_DATA_SIZE_SINT32,
397         reinterpret_cast<uint8_t*>(&effecterValue), 3);
398     ASSERT_EQ(rc, PLDM_ERROR_INVALID_DATA);
399 
400     pldm_pdr_destroy(inPDRRepo);
401     pldm_pdr_destroy(numericEffecterPdrRepo);
402 }
403 
404 TEST(getNumericEffecterValueHandler, testGoodRequest)
405 {
406     MockdBusHandler mockedUtils;
407     EXPECT_CALL(mockedUtils, getService(StrEq("/foo/bar"), _))
408         .Times(5)
409         .WillRepeatedly(Return("foo.bar"));
410 
411     auto inPDRRepo = pldm_pdr_init();
412     auto numericEffecterPdrRepo = pldm_pdr_init();
413     Repo numericEffecterPDRs(numericEffecterPdrRepo);
414     auto event = sdeventplus::Event::get_default();
415     Handler handler(&mockedUtils, 0, nullptr, "./pdr_jsons/state_effecter/good",
416                     inPDRRepo, nullptr, nullptr, nullptr, nullptr, nullptr,
417                     event);
418     Repo inRepo(inPDRRepo);
419     getRepoByType(inRepo, numericEffecterPDRs, PLDM_NUMERIC_EFFECTER_PDR);
420 
421     pdr_utils::PdrEntry e;
422     auto record4 = pdr::getRecordByHandle(numericEffecterPDRs, 4, e);
423     ASSERT_NE(record4, nullptr);
424 
425     pldm_numeric_effecter_value_pdr* pdr =
426         reinterpret_cast<pldm_numeric_effecter_value_pdr*>(e.data);
427     EXPECT_EQ(pdr->hdr.type, PLDM_NUMERIC_EFFECTER_PDR);
428 
429     uint16_t effecterId = 3;
430 
431     uint8_t effecterDataSize{};
432     pldm::utils::PropertyValue dbusValue;
433     std::string propertyType;
434 
435     // effecterValue return the present numeric setting
436     uint32_t effecterValue = 2100000000;
437     using effecterOperationalState = uint8_t;
438     using completionCode = uint8_t;
439 
440     EXPECT_CALL(mockedUtils,
441                 getDbusPropertyVariant(StrEq("/foo/bar"), StrEq("propertyName"),
442                                        StrEq("xyz.openbmc_project.Foo.Bar")))
443         .WillOnce(Return(PropertyValue(static_cast<uint64_t>(effecterValue))));
444 
445     auto rc = platform_numeric_effecter::getNumericEffecterData<
446         MockdBusHandler, Handler>(mockedUtils, handler, effecterId,
447                                   effecterDataSize, propertyType, dbusValue);
448 
449     ASSERT_EQ(rc, 0);
450 
451     size_t responsePayloadLength =
452         sizeof(completionCode) + sizeof(effecterDataSize) +
453         sizeof(effecterOperationalState) +
454         getEffecterDataSize(effecterDataSize) +
455         getEffecterDataSize(effecterDataSize);
456 
457     Response response(responsePayloadLength + sizeof(pldm_msg_hdr));
458     auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
459 
460     rc = platform_numeric_effecter::getNumericEffecterValueHandler(
461         propertyType, dbusValue, effecterDataSize, responsePtr,
462         responsePayloadLength, 1);
463 
464     ASSERT_EQ(rc, 0);
465 
466     struct pldm_get_numeric_effecter_value_resp* resp =
467         reinterpret_cast<struct pldm_get_numeric_effecter_value_resp*>(
468             responsePtr->payload);
469     ASSERT_EQ(PLDM_SUCCESS, resp->completion_code);
470     uint32_t valPresent;
471     memcpy(&valPresent, &resp->pending_and_present_values[4],
472            sizeof(valPresent));
473 
474     ASSERT_EQ(effecterValue, valPresent);
475 
476     pldm_pdr_destroy(inPDRRepo);
477     pldm_pdr_destroy(numericEffecterPdrRepo);
478 }
479 
480 TEST(getNumericEffecterValueHandler, testBadRequest)
481 {
482     MockdBusHandler mockedUtils;
483     EXPECT_CALL(mockedUtils, getService(StrEq("/foo/bar"), _))
484         .Times(5)
485         .WillRepeatedly(Return("foo.bar"));
486 
487     auto inPDRRepo = pldm_pdr_init();
488     auto numericEffecterPdrRepo = pldm_pdr_init();
489     Repo numericEffecterPDRs(numericEffecterPdrRepo);
490     auto event = sdeventplus::Event::get_default();
491     Handler handler(&mockedUtils, 0, nullptr, "./pdr_jsons/state_effecter/good",
492                     inPDRRepo, nullptr, nullptr, nullptr, nullptr, nullptr,
493                     event);
494     Repo inRepo(inPDRRepo);
495     getRepoByType(inRepo, numericEffecterPDRs, PLDM_NUMERIC_EFFECTER_PDR);
496 
497     pdr_utils::PdrEntry e;
498     auto record4 = pdr::getRecordByHandle(numericEffecterPDRs, 4, e);
499     ASSERT_NE(record4, nullptr);
500 
501     pldm_numeric_effecter_value_pdr* pdr =
502         reinterpret_cast<pldm_numeric_effecter_value_pdr*>(e.data);
503     EXPECT_EQ(pdr->hdr.type, PLDM_NUMERIC_EFFECTER_PDR);
504 
505     uint16_t effecterId = 4;
506 
507     uint8_t effecterDataSize{};
508     pldm::utils::PropertyValue dbusValue;
509     std::string propertyType;
510 
511     auto rc = platform_numeric_effecter::getNumericEffecterData<
512         MockdBusHandler, Handler>(mockedUtils, handler, effecterId,
513                                   effecterDataSize, propertyType, dbusValue);
514 
515     ASSERT_EQ(rc, 128);
516 
517     pldm_pdr_destroy(inPDRRepo);
518     pldm_pdr_destroy(numericEffecterPdrRepo);
519 }
520 
521 TEST(parseStateSensor, allScenarios)
522 {
523     // Sample state sensor with SensorID - 1, EntityType - Processor Module(67)
524     // State Set ID - Operational Running Status(11), Supported States - 3,4
525     std::vector<uint8_t> sample1PDR{
526         0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x17,
527         0x00, 0x00, 0x00, 0x01, 0x00, 0x43, 0x00, 0x01, 0x00,
528         0x00, 0x00, 0x00, 0x00, 0x01, 0x0b, 0x00, 0x01, 0x18};
529 
530     const auto& [terminusHandle1, sensorID1, sensorInfo1] =
531         parseStateSensorPDR(sample1PDR);
532     const auto& [containerID1, entityType1, entityInstance1] =
533         std::get<0>(sensorInfo1);
534     const auto& states1 = std::get<1>(sensorInfo1);
535     CompositeSensorStates statesCmp1{{3u, 4u}};
536 
537     ASSERT_EQ(le16toh(terminusHandle1), 0u);
538     ASSERT_EQ(le16toh(sensorID1), 1u);
539     ASSERT_EQ(le16toh(containerID1), 0u);
540     ASSERT_EQ(le16toh(entityType1), 67u);
541     ASSERT_EQ(le16toh(entityInstance1), 1u);
542     ASSERT_EQ(states1, statesCmp1);
543 
544     // Sample state sensor with SensorID - 2, EntityType - System Firmware(31)
545     // State Set ID - Availability(2), Supported States - 3,4,9,10,11,13
546     std::vector<uint8_t> sample2PDR{
547         0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x17, 0x00,
548         0x00, 0x00, 0x02, 0x00, 0x1F, 0x00, 0x01, 0x00, 0x00, 0x00,
549         0x00, 0x00, 0x01, 0x02, 0x00, 0x02, 0x18, 0x2E};
550 
551     const auto& [terminusHandle2, sensorID2, sensorInfo2] =
552         parseStateSensorPDR(sample2PDR);
553     const auto& [containerID2, entityType2, entityInstance2] =
554         std::get<0>(sensorInfo2);
555     const auto& states2 = std::get<1>(sensorInfo2);
556     CompositeSensorStates statesCmp2{{3u, 4u, 9u, 10u, 11u, 13u}};
557 
558     ASSERT_EQ(le16toh(terminusHandle2), 0u);
559     ASSERT_EQ(le16toh(sensorID2), 2u);
560     ASSERT_EQ(le16toh(containerID2), 0u);
561     ASSERT_EQ(le16toh(entityType2), 31u);
562     ASSERT_EQ(le16toh(entityInstance2), 1u);
563     ASSERT_EQ(states2, statesCmp2);
564 
565     // Sample state sensor with SensorID - 3, EntityType - Virtual Machine
566     // Manager(33), Composite State Sensor -2 , State Set ID - Link State(33),
567     // Supported States - 1,2, State Set ID - Configuration State(15),
568     // Supported States - 1,2,3,4
569     std::vector<uint8_t> sample3PDR{
570         0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x17, 0x00, 0x00,
571         0x00, 0x03, 0x00, 0x21, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00,
572         0x02, 0x21, 0x00, 0x01, 0x06, 0x0F, 0x00, 0x01, 0x1E};
573 
574     const auto& [terminusHandle3, sensorID3, sensorInfo3] =
575         parseStateSensorPDR(sample3PDR);
576     const auto& [containerID3, entityType3, entityInstance3] =
577         std::get<0>(sensorInfo3);
578     const auto& states3 = std::get<1>(sensorInfo3);
579     CompositeSensorStates statesCmp3{{1u, 2u}, {1u, 2u, 3u, 4u}};
580 
581     ASSERT_EQ(le16toh(terminusHandle3), 0u);
582     ASSERT_EQ(le16toh(sensorID3), 3u);
583     ASSERT_EQ(le16toh(containerID3), 1u);
584     ASSERT_EQ(le16toh(entityType3), 33u);
585     ASSERT_EQ(le16toh(entityInstance3), 2u);
586     ASSERT_EQ(states3, statesCmp3);
587 }
588 
589 TEST(StateSensorHandler, allScenarios)
590 {
591     using namespace pldm::responder::events;
592 
593     StateSensorHandler handler{"./event_jsons/good"};
594     constexpr uint8_t eventState0 = 0;
595     constexpr uint8_t eventState1 = 1;
596     constexpr uint8_t eventState2 = 2;
597     constexpr uint8_t eventState3 = 3;
598 
599     // Event Entry 1
600     {
601         StateSensorEntry entry{1, 64, 1, 0, 1, false};
602         const auto& [dbusMapping, eventStateMap] = handler.getEventInfo(entry);
603         DBusMapping mapping{"/xyz/abc/def",
604                             "xyz.openbmc_project.example1.value", "value1",
605                             "string"};
606         ASSERT_EQ(mapping == dbusMapping, true);
607 
608         const auto& propValue0 = eventStateMap.at(eventState0);
609         const auto& propValue1 = eventStateMap.at(eventState1);
610         const auto& propValue2 = eventStateMap.at(eventState2);
611         PropertyValue value0{std::in_place_type<std::string>,
612                              "xyz.openbmc_project.State.Normal"};
613         PropertyValue value1{std::in_place_type<std::string>,
614                              "xyz.openbmc_project.State.Critical"};
615         PropertyValue value2{std::in_place_type<std::string>,
616                              "xyz.openbmc_project.State.Fatal"};
617         ASSERT_EQ(value0 == propValue0, true);
618         ASSERT_EQ(value1 == propValue1, true);
619         ASSERT_EQ(value2 == propValue2, true);
620     }
621 
622     // Event Entry 2
623     {
624         StateSensorEntry entry{1, 64, 1, 1, 1, false};
625         const auto& [dbusMapping, eventStateMap] = handler.getEventInfo(entry);
626         DBusMapping mapping{"/xyz/abc/def",
627                             "xyz.openbmc_project.example2.value", "value2",
628                             "uint8_t"};
629         ASSERT_EQ(mapping == dbusMapping, true);
630 
631         const auto& propValue0 = eventStateMap.at(eventState2);
632         const auto& propValue1 = eventStateMap.at(eventState3);
633         PropertyValue value0{std::in_place_type<uint8_t>, 9};
634         PropertyValue value1{std::in_place_type<uint8_t>, 10};
635         ASSERT_EQ(value0 == propValue0, true);
636         ASSERT_EQ(value1 == propValue1, true);
637     }
638 
639     // Event Entry 3
640     {
641         StateSensorEntry entry{2, 67, 2, 0, 1, false};
642         const auto& [dbusMapping, eventStateMap] = handler.getEventInfo(entry);
643         DBusMapping mapping{"/xyz/abc/ghi",
644                             "xyz.openbmc_project.example3.value", "value3",
645                             "bool"};
646         ASSERT_EQ(mapping == dbusMapping, true);
647 
648         const auto& propValue0 = eventStateMap.at(eventState0);
649         const auto& propValue1 = eventStateMap.at(eventState1);
650         PropertyValue value0{std::in_place_type<bool>, false};
651         PropertyValue value1{std::in_place_type<bool>, true};
652         ASSERT_EQ(value0 == propValue0, true);
653         ASSERT_EQ(value1 == propValue1, true);
654     }
655 
656     // Event Entry 4
657     {
658         StateSensorEntry entry{2, 67, 2, 0, 2, false};
659         const auto& [dbusMapping, eventStateMap] = handler.getEventInfo(entry);
660         DBusMapping mapping{"/xyz/abc/jkl",
661                             "xyz.openbmc_project.example4.value", "value4",
662                             "string"};
663         ASSERT_EQ(mapping == dbusMapping, true);
664 
665         const auto& propValue0 = eventStateMap.at(eventState0);
666         const auto& propValue1 = eventStateMap.at(eventState1);
667         const auto& propValue2 = eventStateMap.at(eventState2);
668         PropertyValue value0{std::in_place_type<std::string>, "Enabled"};
669         PropertyValue value1{std::in_place_type<std::string>, "Disabled"};
670         PropertyValue value2{std::in_place_type<std::string>, "Auto"};
671         ASSERT_EQ(value0 == propValue0, true);
672         ASSERT_EQ(value1 == propValue1, true);
673         ASSERT_EQ(value2 == propValue2, true);
674     }
675 
676     // Event Entry 5
677     {
678         StateSensorEntry entry{0xFFFF, 120, 2, 0, 2, true};
679         const auto& [dbusMapping, eventStateMap] = handler.getEventInfo(entry);
680         DBusMapping mapping{"/xyz/abc/mno",
681                             "xyz.openbmc_project.example5.value", "value5",
682                             "string"};
683         ASSERT_EQ(mapping == dbusMapping, true);
684 
685         const auto& propValue0 = eventStateMap.at(eventState0);
686         const auto& propValue1 = eventStateMap.at(eventState1);
687         const auto& propValue2 = eventStateMap.at(eventState2);
688         PropertyValue value0{std::in_place_type<std::string>, "Enabled"};
689         PropertyValue value1{std::in_place_type<std::string>, "Disabled"};
690         PropertyValue value2{std::in_place_type<std::string>, "Auto"};
691         ASSERT_EQ(value0 == propValue0, true);
692         ASSERT_EQ(value1 == propValue1, true);
693         ASSERT_EQ(value2 == propValue2, true);
694     }
695     // Event Entry 6
696     {
697         StateSensorEntry entry{10, 120, 2, 0, 2, true};
698         const auto& [dbusMapping, eventStateMap] = handler.getEventInfo(entry);
699         DBusMapping mapping{"/xyz/abc/opk",
700                             "xyz.openbmc_project.example6.value", "value6",
701                             "string"};
702         ASSERT_EQ(mapping == dbusMapping, true);
703 
704         const auto& propValue0 = eventStateMap.at(eventState0);
705         const auto& propValue1 = eventStateMap.at(eventState1);
706         const auto& propValue2 = eventStateMap.at(eventState2);
707         PropertyValue value0{std::in_place_type<std::string>, "Enabled"};
708         PropertyValue value1{std::in_place_type<std::string>, "Disabled"};
709         PropertyValue value2{std::in_place_type<std::string>, "Auto"};
710         ASSERT_EQ(value0 == propValue0, true);
711         ASSERT_EQ(value1 == propValue1, true);
712         ASSERT_EQ(value2 == propValue2, true);
713     }
714     // Event Entry 7
715     {
716         StateSensorEntry entry{10, 120, 2, 0, 2, false};
717         const auto& [dbusMapping, eventStateMap] = handler.getEventInfo(entry);
718         DBusMapping mapping{"/xyz/abc/opk",
719                             "xyz.openbmc_project.example6.value", "value6",
720                             "string"};
721         ASSERT_EQ(mapping == dbusMapping, true);
722 
723         const auto& propValue0 = eventStateMap.at(eventState0);
724         const auto& propValue1 = eventStateMap.at(eventState1);
725         const auto& propValue2 = eventStateMap.at(eventState2);
726         PropertyValue value0{std::in_place_type<std::string>, "Enabled"};
727         PropertyValue value1{std::in_place_type<std::string>, "Disabled"};
728         PropertyValue value2{std::in_place_type<std::string>, "Auto"};
729         ASSERT_EQ(value0 == propValue0, true);
730         ASSERT_EQ(value1 == propValue1, true);
731         ASSERT_EQ(value2 == propValue2, true);
732     }
733 
734     // Invalid Entry
735     {
736         StateSensorEntry entry{0, 0, 0, 0, 1, false};
737         ASSERT_THROW(handler.getEventInfo(entry), std::out_of_range);
738     }
739 }
740 
741 TEST(TerminusLocatorPDR, BMCTerminusLocatorPDR)
742 {
743     auto inPDRRepo = pldm_pdr_init();
744     auto outPDRRepo = pldm_pdr_init();
745     Repo outRepo(outPDRRepo);
746     MockdBusHandler mockedUtils;
747     auto event = sdeventplus::Event::get_default();
748     Handler handler(&mockedUtils, 0, nullptr, "", inPDRRepo, nullptr, nullptr,
749                     nullptr, nullptr, nullptr, event);
750     Repo inRepo(inPDRRepo);
751     getRepoByType(inRepo, outRepo, PLDM_TERMINUS_LOCATOR_PDR);
752 
753     // 1 BMC terminus locator PDR in the PDR repository
754     ASSERT_EQ(outRepo.getRecordCount(), 1);
755 
756     pdr_utils::PdrEntry entry;
757     auto record = pdr::getRecordByHandle(outRepo, 1, entry);
758     ASSERT_NE(record, nullptr);
759 
760     auto pdr = reinterpret_cast<const pldm_terminus_locator_pdr*>(entry.data);
761     EXPECT_EQ(pdr->hdr.record_handle, 1);
762     EXPECT_EQ(pdr->hdr.version, 1);
763     EXPECT_EQ(pdr->hdr.type, PLDM_TERMINUS_LOCATOR_PDR);
764     EXPECT_EQ(pdr->hdr.record_change_num, 0);
765     EXPECT_EQ(pdr->hdr.length,
766               sizeof(pldm_terminus_locator_pdr) - sizeof(pldm_pdr_hdr));
767     EXPECT_EQ(pdr->terminus_handle, TERMINUS_HANDLE);
768     EXPECT_EQ(pdr->validity, PLDM_TL_PDR_VALID);
769     EXPECT_EQ(pdr->tid, TERMINUS_ID);
770     EXPECT_EQ(pdr->container_id, 0);
771     EXPECT_EQ(pdr->terminus_locator_type, PLDM_TERMINUS_LOCATOR_TYPE_MCTP_EID);
772     EXPECT_EQ(pdr->terminus_locator_value_size,
773               sizeof(pldm_terminus_locator_type_mctp_eid));
774     auto locatorValue =
775         reinterpret_cast<const pldm_terminus_locator_type_mctp_eid*>(
776             pdr->terminus_locator_value);
777     EXPECT_EQ(locatorValue->eid, BmcMctpEid);
778     pldm_pdr_destroy(inPDRRepo);
779     pldm_pdr_destroy(outPDRRepo);
780 }
781 
782 TEST(getStateSensorReadingsHandler, testGoodRequest)
783 {
784     MockdBusHandler mockedUtils;
785     EXPECT_CALL(mockedUtils, getService(StrEq("/foo/bar"), _))
786         .Times(1)
787         .WillRepeatedly(Return("foo.bar"));
788 
789     auto inPDRRepo = pldm_pdr_init();
790     auto outPDRRepo = pldm_pdr_init();
791     Repo outRepo(outPDRRepo);
792     auto event = sdeventplus::Event::get_default();
793     Handler handler(&mockedUtils, 0, nullptr, "./pdr_jsons/state_sensor/good",
794                     inPDRRepo, nullptr, nullptr, nullptr, nullptr, nullptr,
795                     event);
796     Repo inRepo(inPDRRepo);
797     getRepoByType(inRepo, outRepo, PLDM_STATE_SENSOR_PDR);
798     pdr_utils::PdrEntry e;
799     auto record = pdr::getRecordByHandle(outRepo, 2, e);
800     ASSERT_NE(record, nullptr);
801     pldm_state_sensor_pdr* pdr =
802         reinterpret_cast<pldm_state_sensor_pdr*>(e.data);
803     EXPECT_EQ(pdr->hdr.type, PLDM_STATE_SENSOR_PDR);
804 
805     std::vector<get_sensor_state_field> stateField;
806     uint8_t compSensorCnt{};
807     uint8_t sensorRearmCnt = 1;
808 
809     MockdBusHandler handlerObj;
810     EXPECT_CALL(handlerObj,
811                 getDbusPropertyVariant(StrEq("/foo/bar"), StrEq("propertyName"),
812                                        StrEq("xyz.openbmc_project.Foo.Bar")))
813         .WillOnce(Return(
814             PropertyValue(std::string("xyz.openbmc_project.Foo.Bar.V0"))));
815     EventStates cache = {PLDM_SENSOR_NORMAL};
816     pldm::stateSensorCacheMaps sensorCache;
817     sensorCache.emplace(0x1, cache);
818     auto rc = platform_state_sensor::getStateSensorReadingsHandler<
819         MockdBusHandler, Handler>(handlerObj, handler, 0x1, sensorRearmCnt,
820                                   compSensorCnt, stateField, sensorCache);
821     ASSERT_EQ(rc, 0);
822     ASSERT_EQ(compSensorCnt, 1);
823     ASSERT_EQ(stateField[0].sensor_op_state, PLDM_SENSOR_UNAVAILABLE);
824     ASSERT_EQ(stateField[0].present_state, PLDM_SENSOR_NORMAL);
825     ASSERT_EQ(stateField[0].previous_state, PLDM_SENSOR_NORMAL);
826     ASSERT_EQ(stateField[0].event_state, PLDM_SENSOR_UNKNOWN);
827 
828     pldm_pdr_destroy(inPDRRepo);
829     pldm_pdr_destroy(outPDRRepo);
830 }
831 
832 TEST(getStateSensorReadingsHandler, testBadRequest)
833 {
834     MockdBusHandler mockedUtils;
835     EXPECT_CALL(mockedUtils, getService(StrEq("/foo/bar"), _))
836         .Times(1)
837         .WillRepeatedly(Return("foo.bar"));
838 
839     auto inPDRRepo = pldm_pdr_init();
840     auto outPDRRepo = pldm_pdr_init();
841     Repo outRepo(outPDRRepo);
842     auto event = sdeventplus::Event::get_default();
843     Handler handler(&mockedUtils, 0, nullptr, "./pdr_jsons/state_sensor/good",
844                     inPDRRepo, nullptr, nullptr, nullptr, nullptr, nullptr,
845                     event);
846     Repo inRepo(inPDRRepo);
847     getRepoByType(inRepo, outRepo, PLDM_STATE_SENSOR_PDR);
848     pdr_utils::PdrEntry e;
849     auto record = pdr::getRecordByHandle(outRepo, 2, e);
850     ASSERT_NE(record, nullptr);
851     pldm_state_sensor_pdr* pdr =
852         reinterpret_cast<pldm_state_sensor_pdr*>(e.data);
853     EXPECT_EQ(pdr->hdr.type, PLDM_STATE_SENSOR_PDR);
854 
855     std::vector<get_sensor_state_field> stateField;
856     uint8_t compSensorCnt{};
857     uint8_t sensorRearmCnt = 3;
858 
859     MockdBusHandler handlerObj;
860     EventStates cache = {PLDM_SENSOR_NORMAL};
861     pldm::stateSensorCacheMaps sensorCache;
862     sensorCache.emplace(0x1, cache);
863     auto rc = platform_state_sensor::getStateSensorReadingsHandler<
864         MockdBusHandler, Handler>(handlerObj, handler, 0x1, sensorRearmCnt,
865                                   compSensorCnt, stateField, sensorCache);
866     ASSERT_EQ(rc, PLDM_PLATFORM_REARM_UNAVAILABLE_IN_PRESENT_STATE);
867 
868     pldm_pdr_destroy(inPDRRepo);
869     pldm_pdr_destroy(outPDRRepo);
870 }
871