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