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