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