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