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