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