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 nullptr, 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 nullptr, 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 nullptr, 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 nullptr, 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 nullptr, 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 nullptr, 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 nullptr, 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 nullptr, 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 nullptr, 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 nullptr, 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 nullptr, 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}; 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}; 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}; 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}; 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 // Invalid Entry 681 { 682 StateSensorEntry entry{0, 0, 0, 0, 1}; 683 ASSERT_THROW(handler.getEventInfo(entry), std::out_of_range); 684 } 685 } 686 687 TEST(TerminusLocatorPDR, BMCTerminusLocatorPDR) 688 { 689 auto inPDRRepo = pldm_pdr_init(); 690 auto outPDRRepo = pldm_pdr_init(); 691 Repo outRepo(outPDRRepo); 692 MockdBusHandler mockedUtils; 693 auto event = sdeventplus::Event::get_default(); 694 Handler handler(&mockedUtils, 0, nullptr, "", inPDRRepo, nullptr, nullptr, 695 nullptr, nullptr, nullptr, nullptr, event); 696 Repo inRepo(inPDRRepo); 697 getRepoByType(inRepo, outRepo, PLDM_TERMINUS_LOCATOR_PDR); 698 699 // 1 BMC terminus locator PDR in the PDR repository 700 ASSERT_EQ(outRepo.getRecordCount(), 1); 701 702 pdr_utils::PdrEntry entry; 703 auto record = pdr::getRecordByHandle(outRepo, 1, entry); 704 ASSERT_NE(record, nullptr); 705 706 auto pdr = reinterpret_cast<const pldm_terminus_locator_pdr*>(entry.data); 707 EXPECT_EQ(pdr->hdr.record_handle, 1); 708 EXPECT_EQ(pdr->hdr.version, 1); 709 EXPECT_EQ(pdr->hdr.type, PLDM_TERMINUS_LOCATOR_PDR); 710 EXPECT_EQ(pdr->hdr.record_change_num, 0); 711 EXPECT_EQ(pdr->hdr.length, 712 sizeof(pldm_terminus_locator_pdr) - sizeof(pldm_pdr_hdr)); 713 EXPECT_EQ(pdr->terminus_handle, TERMINUS_HANDLE); 714 EXPECT_EQ(pdr->validity, PLDM_TL_PDR_VALID); 715 EXPECT_EQ(pdr->tid, TERMINUS_ID); 716 EXPECT_EQ(pdr->container_id, 0); 717 EXPECT_EQ(pdr->terminus_locator_type, PLDM_TERMINUS_LOCATOR_TYPE_MCTP_EID); 718 EXPECT_EQ(pdr->terminus_locator_value_size, 719 sizeof(pldm_terminus_locator_type_mctp_eid)); 720 auto locatorValue = 721 reinterpret_cast<const pldm_terminus_locator_type_mctp_eid*>( 722 pdr->terminus_locator_value); 723 EXPECT_EQ(locatorValue->eid, BmcMctpEid); 724 pldm_pdr_destroy(inPDRRepo); 725 pldm_pdr_destroy(outPDRRepo); 726 } 727 728 TEST(getStateSensorReadingsHandler, testGoodRequest) 729 { 730 MockdBusHandler mockedUtils; 731 EXPECT_CALL(mockedUtils, getService(StrEq("/foo/bar"), _)) 732 .Times(1) 733 .WillRepeatedly(Return("foo.bar")); 734 735 auto inPDRRepo = pldm_pdr_init(); 736 auto outPDRRepo = pldm_pdr_init(); 737 Repo outRepo(outPDRRepo); 738 auto event = sdeventplus::Event::get_default(); 739 Handler handler(&mockedUtils, 0, nullptr, "./pdr_jsons/state_sensor/good", 740 inPDRRepo, nullptr, nullptr, nullptr, nullptr, nullptr, 741 nullptr, event); 742 Repo inRepo(inPDRRepo); 743 getRepoByType(inRepo, outRepo, PLDM_STATE_SENSOR_PDR); 744 pdr_utils::PdrEntry e; 745 auto record = pdr::getRecordByHandle(outRepo, 2, e); 746 ASSERT_NE(record, nullptr); 747 pldm_state_sensor_pdr* pdr = 748 reinterpret_cast<pldm_state_sensor_pdr*>(e.data); 749 EXPECT_EQ(pdr->hdr.type, PLDM_STATE_SENSOR_PDR); 750 751 std::vector<get_sensor_state_field> stateField; 752 uint8_t compSensorCnt{}; 753 uint8_t sensorRearmCnt = 1; 754 755 MockdBusHandler handlerObj; 756 EXPECT_CALL(handlerObj, 757 getDbusPropertyVariant(StrEq("/foo/bar"), StrEq("propertyName"), 758 StrEq("xyz.openbmc_project.Foo.Bar"))) 759 .WillOnce(Return( 760 PropertyValue(std::string("xyz.openbmc_project.Foo.Bar.V0")))); 761 EventStates cache = {PLDM_SENSOR_NORMAL}; 762 pldm::stateSensorCacheMaps sensorCache; 763 sensorCache.emplace(0x1, cache); 764 auto rc = platform_state_sensor::getStateSensorReadingsHandler< 765 MockdBusHandler, Handler>(handlerObj, handler, 0x1, sensorRearmCnt, 766 compSensorCnt, stateField, sensorCache); 767 ASSERT_EQ(rc, 0); 768 ASSERT_EQ(compSensorCnt, 1); 769 ASSERT_EQ(stateField[0].sensor_op_state, PLDM_SENSOR_UNAVAILABLE); 770 ASSERT_EQ(stateField[0].present_state, PLDM_SENSOR_NORMAL); 771 ASSERT_EQ(stateField[0].previous_state, PLDM_SENSOR_NORMAL); 772 ASSERT_EQ(stateField[0].event_state, PLDM_SENSOR_UNKNOWN); 773 774 pldm_pdr_destroy(inPDRRepo); 775 pldm_pdr_destroy(outPDRRepo); 776 } 777 778 TEST(getStateSensorReadingsHandler, testBadRequest) 779 { 780 MockdBusHandler mockedUtils; 781 EXPECT_CALL(mockedUtils, getService(StrEq("/foo/bar"), _)) 782 .Times(1) 783 .WillRepeatedly(Return("foo.bar")); 784 785 auto inPDRRepo = pldm_pdr_init(); 786 auto outPDRRepo = pldm_pdr_init(); 787 Repo outRepo(outPDRRepo); 788 auto event = sdeventplus::Event::get_default(); 789 Handler handler(&mockedUtils, 0, nullptr, "./pdr_jsons/state_sensor/good", 790 inPDRRepo, nullptr, nullptr, nullptr, nullptr, nullptr, 791 nullptr, event); 792 Repo inRepo(inPDRRepo); 793 getRepoByType(inRepo, outRepo, PLDM_STATE_SENSOR_PDR); 794 pdr_utils::PdrEntry e; 795 auto record = pdr::getRecordByHandle(outRepo, 2, e); 796 ASSERT_NE(record, nullptr); 797 pldm_state_sensor_pdr* pdr = 798 reinterpret_cast<pldm_state_sensor_pdr*>(e.data); 799 EXPECT_EQ(pdr->hdr.type, PLDM_STATE_SENSOR_PDR); 800 801 std::vector<get_sensor_state_field> stateField; 802 uint8_t compSensorCnt{}; 803 uint8_t sensorRearmCnt = 3; 804 805 MockdBusHandler handlerObj; 806 EventStates cache = {PLDM_SENSOR_NORMAL}; 807 pldm::stateSensorCacheMaps sensorCache; 808 sensorCache.emplace(0x1, cache); 809 auto rc = platform_state_sensor::getStateSensorReadingsHandler< 810 MockdBusHandler, Handler>(handlerObj, handler, 0x1, sensorRearmCnt, 811 compSensorCnt, stateField, sensorCache); 812 ASSERT_EQ(rc, PLDM_PLATFORM_REARM_UNAVAILABLE_IN_PRESENT_STATE); 813 814 pldm_pdr_destroy(inPDRRepo); 815 pldm_pdr_destroy(outPDRRepo); 816 } 817