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