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