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