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