blob: d3606f5eb5914994946fc76b600d7cb93e08b3fd [file] [log] [blame]
#include "common/test/mocked_utils.hpp"
#include "common/utils.hpp"
#include "host-bmc/dbus_to_event_handler.hpp"
#include "libpldmresponder/event_parser.hpp"
#include "libpldmresponder/pdr.hpp"
#include "libpldmresponder/pdr_utils.hpp"
#include "libpldmresponder/platform.hpp"
#include "libpldmresponder/platform_numeric_effecter.hpp"
#include "libpldmresponder/platform_state_effecter.hpp"
#include "libpldmresponder/platform_state_sensor.hpp"
#include <sdbusplus/test/sdbus_mock.hpp>
#include <sdeventplus/event.hpp>
using namespace pldm::pdr;
using namespace pldm::utils;
using namespace pldm::responder;
using namespace pldm::responder::platform;
using namespace pldm::responder::pdr;
using namespace pldm::responder::pdr_utils;
using ::testing::_;
using ::testing::Return;
using ::testing::StrEq;
TEST(getPDR, testGoodPath)
{
std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_GET_PDR_REQ_BYTES>
requestPayload{};
auto req = reinterpret_cast<pldm_msg*>(requestPayload.data());
size_t requestPayloadLength = requestPayload.size() - sizeof(pldm_msg_hdr);
struct pldm_get_pdr_req* request =
reinterpret_cast<struct pldm_get_pdr_req*>(req->payload);
request->request_count = 100;
MockdBusHandler mockedUtils;
EXPECT_CALL(mockedUtils, getService(StrEq("/foo/bar"), _))
.Times(5)
.WillRepeatedly(Return("foo.bar"));
auto pdrRepo = pldm_pdr_init();
auto event = sdeventplus::Event::get_default();
Handler handler(&mockedUtils, 0, nullptr, "./pdr_jsons/state_effecter/good",
pdrRepo, nullptr, nullptr, nullptr, nullptr, nullptr,
event);
Repo repo(pdrRepo);
ASSERT_EQ(repo.empty(), false);
auto response = handler.getPDR(req, requestPayloadLength);
auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
struct pldm_get_pdr_resp* resp =
reinterpret_cast<struct pldm_get_pdr_resp*>(responsePtr->payload);
ASSERT_EQ(PLDM_SUCCESS, resp->completion_code);
ASSERT_EQ(2, resp->next_record_handle);
ASSERT_EQ(true, resp->response_count != 0);
pldm_pdr_hdr* hdr = reinterpret_cast<pldm_pdr_hdr*>(resp->record_data);
ASSERT_EQ(hdr->record_handle, 1);
ASSERT_EQ(hdr->version, 1);
pldm_pdr_destroy(pdrRepo);
}
TEST(getPDR, testShortRead)
{
std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_GET_PDR_REQ_BYTES>
requestPayload{};
auto req = reinterpret_cast<pldm_msg*>(requestPayload.data());
size_t requestPayloadLength = requestPayload.size() - sizeof(pldm_msg_hdr);
struct pldm_get_pdr_req* request =
reinterpret_cast<struct pldm_get_pdr_req*>(req->payload);
request->request_count = 1;
MockdBusHandler mockedUtils;
EXPECT_CALL(mockedUtils, getService(StrEq("/foo/bar"), _))
.Times(5)
.WillRepeatedly(Return("foo.bar"));
auto pdrRepo = pldm_pdr_init();
auto event = sdeventplus::Event::get_default();
Handler handler(&mockedUtils, 0, nullptr, "./pdr_jsons/state_effecter/good",
pdrRepo, nullptr, nullptr, nullptr, nullptr, nullptr,
event);
Repo repo(pdrRepo);
ASSERT_EQ(repo.empty(), false);
auto response = handler.getPDR(req, requestPayloadLength);
auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
struct pldm_get_pdr_resp* resp =
reinterpret_cast<struct pldm_get_pdr_resp*>(responsePtr->payload);
ASSERT_EQ(PLDM_SUCCESS, resp->completion_code);
ASSERT_EQ(1, resp->response_count);
pldm_pdr_destroy(pdrRepo);
}
TEST(getPDR, testBadRecordHandle)
{
std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_GET_PDR_REQ_BYTES>
requestPayload{};
auto req = reinterpret_cast<pldm_msg*>(requestPayload.data());
size_t requestPayloadLength = requestPayload.size() - sizeof(pldm_msg_hdr);
struct pldm_get_pdr_req* request =
reinterpret_cast<struct pldm_get_pdr_req*>(req->payload);
request->record_handle = 100000;
request->request_count = 1;
MockdBusHandler mockedUtils;
EXPECT_CALL(mockedUtils, getService(StrEq("/foo/bar"), _))
.Times(5)
.WillRepeatedly(Return("foo.bar"));
auto pdrRepo = pldm_pdr_init();
auto event = sdeventplus::Event::get_default();
Handler handler(&mockedUtils, 0, nullptr, "./pdr_jsons/state_effecter/good",
pdrRepo, nullptr, nullptr, nullptr, nullptr, nullptr,
event);
Repo repo(pdrRepo);
ASSERT_EQ(repo.empty(), false);
auto response = handler.getPDR(req, requestPayloadLength);
auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
ASSERT_EQ(responsePtr->payload[0], PLDM_PLATFORM_INVALID_RECORD_HANDLE);
pldm_pdr_destroy(pdrRepo);
}
TEST(getPDR, testNoNextRecord)
{
std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_GET_PDR_REQ_BYTES>
requestPayload{};
auto req = reinterpret_cast<pldm_msg*>(requestPayload.data());
size_t requestPayloadLength = requestPayload.size() - sizeof(pldm_msg_hdr);
struct pldm_get_pdr_req* request =
reinterpret_cast<struct pldm_get_pdr_req*>(req->payload);
request->record_handle = 1;
MockdBusHandler mockedUtils;
EXPECT_CALL(mockedUtils, getService(StrEq("/foo/bar"), _))
.Times(5)
.WillRepeatedly(Return("foo.bar"));
auto pdrRepo = pldm_pdr_init();
auto event = sdeventplus::Event::get_default();
Handler handler(&mockedUtils, 0, nullptr, "./pdr_jsons/state_effecter/good",
pdrRepo, nullptr, nullptr, nullptr, nullptr, nullptr,
event);
Repo repo(pdrRepo);
ASSERT_EQ(repo.empty(), false);
auto response = handler.getPDR(req, requestPayloadLength);
auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
struct pldm_get_pdr_resp* resp =
reinterpret_cast<struct pldm_get_pdr_resp*>(responsePtr->payload);
ASSERT_EQ(PLDM_SUCCESS, resp->completion_code);
ASSERT_EQ(2, resp->next_record_handle);
pldm_pdr_destroy(pdrRepo);
}
TEST(getPDR, testFindPDR)
{
std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_GET_PDR_REQ_BYTES>
requestPayload{};
auto req = reinterpret_cast<pldm_msg*>(requestPayload.data());
size_t requestPayloadLength = requestPayload.size() - sizeof(pldm_msg_hdr);
struct pldm_get_pdr_req* request =
reinterpret_cast<struct pldm_get_pdr_req*>(req->payload);
request->request_count = 100;
MockdBusHandler mockedUtils;
EXPECT_CALL(mockedUtils, getService(StrEq("/foo/bar"), _))
.Times(5)
.WillRepeatedly(Return("foo.bar"));
auto pdrRepo = pldm_pdr_init();
auto event = sdeventplus::Event::get_default();
Handler handler(&mockedUtils, 0, nullptr, "./pdr_jsons/state_effecter/good",
pdrRepo, nullptr, nullptr, nullptr, nullptr, nullptr,
event);
Repo repo(pdrRepo);
ASSERT_EQ(repo.empty(), false);
auto response = handler.getPDR(req, requestPayloadLength);
// Let's try to find a PDR of type stateEffecter (= 11) and entity type =
// 100
bool found = false;
uint32_t handle = 0; // start asking for PDRs from recordHandle 0
while (!found)
{
request->record_handle = handle;
auto response = handler.getPDR(req, requestPayloadLength);
auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
struct pldm_get_pdr_resp* resp =
reinterpret_cast<struct pldm_get_pdr_resp*>(responsePtr->payload);
ASSERT_EQ(PLDM_SUCCESS, resp->completion_code);
handle = resp->next_record_handle; // point to the next pdr in case
// current is not what we want
pldm_pdr_hdr* hdr = reinterpret_cast<pldm_pdr_hdr*>(resp->record_data);
if (hdr->type == PLDM_STATE_EFFECTER_PDR)
{
pldm_state_effecter_pdr* pdr =
reinterpret_cast<pldm_state_effecter_pdr*>(resp->record_data);
if (pdr->entity_type == 100)
{
found = true;
// Rest of the PDR can be accessed as need be
break;
}
}
if (!resp->next_record_handle) // no more records
{
break;
}
}
ASSERT_EQ(found, true);
pldm_pdr_destroy(pdrRepo);
}
TEST(setStateEffecterStatesHandler, testGoodRequest)
{
std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_GET_PDR_REQ_BYTES>
requestPayload{};
auto req = reinterpret_cast<pldm_msg*>(requestPayload.data());
size_t requestPayloadLength = requestPayload.size() - sizeof(pldm_msg_hdr);
MockdBusHandler mockedUtils;
EXPECT_CALL(mockedUtils, getService(StrEq("/foo/bar"), _))
.Times(5)
.WillRepeatedly(Return("foo.bar"));
auto inPDRRepo = pldm_pdr_init();
auto outPDRRepo = pldm_pdr_init();
Repo outRepo(outPDRRepo);
auto event = sdeventplus::Event::get_default();
Handler handler(&mockedUtils, 0, nullptr, "./pdr_jsons/state_effecter/good",
inPDRRepo, nullptr, nullptr, nullptr, nullptr, nullptr,
event);
handler.getPDR(req, requestPayloadLength);
Repo inRepo(inPDRRepo);
getRepoByType(inRepo, outRepo, PLDM_STATE_EFFECTER_PDR);
pdr_utils::PdrEntry e;
auto record1 = pdr::getRecordByHandle(outRepo, 2, e);
ASSERT_NE(record1, nullptr);
pldm_state_effecter_pdr* pdr =
reinterpret_cast<pldm_state_effecter_pdr*>(e.data);
EXPECT_EQ(pdr->hdr.type, PLDM_STATE_EFFECTER_PDR);
std::vector<set_effecter_state_field> stateField;
stateField.push_back({PLDM_REQUEST_SET, 1});
stateField.push_back({PLDM_REQUEST_SET, 1});
std::string value = "xyz.openbmc_project.Foo.Bar.V1";
PropertyValue propertyValue = value;
DBusMapping dbusMapping{"/foo/bar", "xyz.openbmc_project.Foo.Bar",
"propertyName", "string"};
EXPECT_CALL(mockedUtils, setDbusProperty(dbusMapping, propertyValue))
.Times(2);
auto rc = platform_state_effecter::setStateEffecterStatesHandler<
MockdBusHandler, Handler>(mockedUtils, handler, 0x1, stateField);
ASSERT_EQ(rc, 0);
pldm_pdr_destroy(inPDRRepo);
pldm_pdr_destroy(outPDRRepo);
}
TEST(setStateEffecterStatesHandler, testBadRequest)
{
std::array<uint8_t, sizeof(pldm_msg_hdr) + PLDM_GET_PDR_REQ_BYTES>
requestPayload{};
auto req = reinterpret_cast<pldm_msg*>(requestPayload.data());
size_t requestPayloadLength = requestPayload.size() - sizeof(pldm_msg_hdr);
MockdBusHandler mockedUtils;
EXPECT_CALL(mockedUtils, getService(StrEq("/foo/bar"), _))
.Times(5)
.WillRepeatedly(Return("foo.bar"));
auto inPDRRepo = pldm_pdr_init();
auto outPDRRepo = pldm_pdr_init();
Repo outRepo(outPDRRepo);
auto event = sdeventplus::Event::get_default();
Handler handler(&mockedUtils, 0, nullptr, "./pdr_jsons/state_effecter/good",
inPDRRepo, nullptr, nullptr, nullptr, nullptr, nullptr,
event);
handler.getPDR(req, requestPayloadLength);
Repo inRepo(inPDRRepo);
getRepoByType(inRepo, outRepo, PLDM_STATE_EFFECTER_PDR);
pdr_utils::PdrEntry e;
auto record1 = pdr::getRecordByHandle(outRepo, 2, e);
ASSERT_NE(record1, nullptr);
pldm_state_effecter_pdr* pdr =
reinterpret_cast<pldm_state_effecter_pdr*>(e.data);
EXPECT_EQ(pdr->hdr.type, PLDM_STATE_EFFECTER_PDR);
std::vector<set_effecter_state_field> stateField;
stateField.push_back({PLDM_REQUEST_SET, 3});
stateField.push_back({PLDM_REQUEST_SET, 4});
auto rc = platform_state_effecter::setStateEffecterStatesHandler<
MockdBusHandler, Handler>(mockedUtils, handler, 0x1, stateField);
ASSERT_EQ(rc, PLDM_PLATFORM_SET_EFFECTER_UNSUPPORTED_SENSORSTATE);
rc = platform_state_effecter::setStateEffecterStatesHandler<
MockdBusHandler, Handler>(mockedUtils, handler, 0x9, stateField);
ASSERT_EQ(rc, PLDM_PLATFORM_INVALID_EFFECTER_ID);
stateField.push_back({PLDM_REQUEST_SET, 4});
rc = platform_state_effecter::setStateEffecterStatesHandler<
MockdBusHandler, Handler>(mockedUtils, handler, 0x1, stateField);
ASSERT_EQ(rc, PLDM_ERROR_INVALID_DATA);
pldm_pdr_destroy(inPDRRepo);
pldm_pdr_destroy(outPDRRepo);
}
TEST(setNumericEffecterValueHandler, testGoodRequest)
{
MockdBusHandler mockedUtils;
EXPECT_CALL(mockedUtils, getService(StrEq("/foo/bar"), _))
.Times(5)
.WillRepeatedly(Return("foo.bar"));
auto inPDRRepo = pldm_pdr_init();
auto numericEffecterPdrRepo = pldm_pdr_init();
Repo numericEffecterPDRs(numericEffecterPdrRepo);
auto event = sdeventplus::Event::get_default();
Handler handler(&mockedUtils, 0, nullptr, "./pdr_jsons/state_effecter/good",
inPDRRepo, nullptr, nullptr, nullptr, nullptr, nullptr,
event);
Repo inRepo(inPDRRepo);
getRepoByType(inRepo, numericEffecterPDRs, PLDM_NUMERIC_EFFECTER_PDR);
pdr_utils::PdrEntry e;
auto record4 = pdr::getRecordByHandle(numericEffecterPDRs, 4, e);
ASSERT_NE(record4, nullptr);
pldm_numeric_effecter_value_pdr* pdr =
reinterpret_cast<pldm_numeric_effecter_value_pdr*>(e.data);
EXPECT_EQ(pdr->hdr.type, PLDM_NUMERIC_EFFECTER_PDR);
uint16_t effecterId = 3;
uint32_t effecterValue = 2100000000; // 2036-07-18 21:20:00
PropertyValue propertyValue = static_cast<uint64_t>(effecterValue);
DBusMapping dbusMapping{"/foo/bar", "xyz.openbmc_project.Foo.Bar",
"propertyName", "uint64_t"};
EXPECT_CALL(mockedUtils, setDbusProperty(dbusMapping, propertyValue))
.Times(1);
auto rc = platform_numeric_effecter::setNumericEffecterValueHandler<
MockdBusHandler, Handler>(
mockedUtils, handler, effecterId, PLDM_EFFECTER_DATA_SIZE_UINT32,
reinterpret_cast<uint8_t*>(&effecterValue), 4);
ASSERT_EQ(rc, 0);
pldm_pdr_destroy(inPDRRepo);
pldm_pdr_destroy(numericEffecterPdrRepo);
}
TEST(setNumericEffecterValueHandler, testBadRequest)
{
MockdBusHandler mockedUtils;
EXPECT_CALL(mockedUtils, getService(StrEq("/foo/bar"), _))
.Times(5)
.WillRepeatedly(Return("foo.bar"));
auto inPDRRepo = pldm_pdr_init();
auto numericEffecterPdrRepo = pldm_pdr_init();
Repo numericEffecterPDRs(numericEffecterPdrRepo);
auto event = sdeventplus::Event::get_default();
Handler handler(&mockedUtils, 0, nullptr, "./pdr_jsons/state_effecter/good",
inPDRRepo, nullptr, nullptr, nullptr, nullptr, nullptr,
event);
Repo inRepo(inPDRRepo);
getRepoByType(inRepo, numericEffecterPDRs, PLDM_NUMERIC_EFFECTER_PDR);
pdr_utils::PdrEntry e;
auto record4 = pdr::getRecordByHandle(numericEffecterPDRs, 4, e);
ASSERT_NE(record4, nullptr);
pldm_numeric_effecter_value_pdr* pdr =
reinterpret_cast<pldm_numeric_effecter_value_pdr*>(e.data);
EXPECT_EQ(pdr->hdr.type, PLDM_NUMERIC_EFFECTER_PDR);
uint16_t effecterId = 3;
uint64_t effecterValue = 9876543210;
auto rc = platform_numeric_effecter::setNumericEffecterValueHandler<
MockdBusHandler, Handler>(
mockedUtils, handler, effecterId, PLDM_EFFECTER_DATA_SIZE_SINT32,
reinterpret_cast<uint8_t*>(&effecterValue), 3);
ASSERT_EQ(rc, PLDM_ERROR_INVALID_DATA);
pldm_pdr_destroy(inPDRRepo);
pldm_pdr_destroy(numericEffecterPdrRepo);
}
TEST(getNumericEffecterValueHandler, testGoodRequest)
{
MockdBusHandler mockedUtils;
EXPECT_CALL(mockedUtils, getService(StrEq("/foo/bar"), _))
.Times(5)
.WillRepeatedly(Return("foo.bar"));
auto inPDRRepo = pldm_pdr_init();
auto numericEffecterPdrRepo = pldm_pdr_init();
Repo numericEffecterPDRs(numericEffecterPdrRepo);
auto event = sdeventplus::Event::get_default();
Handler handler(&mockedUtils, 0, nullptr, "./pdr_jsons/state_effecter/good",
inPDRRepo, nullptr, nullptr, nullptr, nullptr, nullptr,
event);
Repo inRepo(inPDRRepo);
getRepoByType(inRepo, numericEffecterPDRs, PLDM_NUMERIC_EFFECTER_PDR);
pdr_utils::PdrEntry e;
auto record4 = pdr::getRecordByHandle(numericEffecterPDRs, 4, e);
ASSERT_NE(record4, nullptr);
pldm_numeric_effecter_value_pdr* pdr =
reinterpret_cast<pldm_numeric_effecter_value_pdr*>(e.data);
EXPECT_EQ(pdr->hdr.type, PLDM_NUMERIC_EFFECTER_PDR);
uint16_t effecterId = 3;
uint8_t effecterDataSize{};
pldm::utils::PropertyValue dbusValue;
std::string propertyType;
// effecterValue return the present numeric setting
uint32_t effecterValue = 2100000000;
using effecterOperationalState = uint8_t;
using completionCode = uint8_t;
EXPECT_CALL(mockedUtils,
getDbusPropertyVariant(StrEq("/foo/bar"), StrEq("propertyName"),
StrEq("xyz.openbmc_project.Foo.Bar")))
.WillOnce(Return(PropertyValue(static_cast<uint64_t>(effecterValue))));
auto rc = platform_numeric_effecter::getNumericEffecterData<
MockdBusHandler, Handler>(mockedUtils, handler, effecterId,
effecterDataSize, propertyType, dbusValue);
ASSERT_EQ(rc, 0);
size_t responsePayloadLength =
sizeof(completionCode) + sizeof(effecterDataSize) +
sizeof(effecterOperationalState) +
getEffecterDataSize(effecterDataSize) +
getEffecterDataSize(effecterDataSize);
Response response(responsePayloadLength + sizeof(pldm_msg_hdr));
auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());
rc = platform_numeric_effecter::getNumericEffecterValueHandler(
propertyType, dbusValue, effecterDataSize, responsePtr,
responsePayloadLength, 1);
ASSERT_EQ(rc, 0);
struct pldm_get_numeric_effecter_value_resp* resp =
reinterpret_cast<struct pldm_get_numeric_effecter_value_resp*>(
responsePtr->payload);
ASSERT_EQ(PLDM_SUCCESS, resp->completion_code);
uint32_t valPresent;
memcpy(&valPresent, &resp->pending_and_present_values[4],
sizeof(valPresent));
ASSERT_EQ(effecterValue, valPresent);
pldm_pdr_destroy(inPDRRepo);
pldm_pdr_destroy(numericEffecterPdrRepo);
}
TEST(getNumericEffecterValueHandler, testBadRequest)
{
MockdBusHandler mockedUtils;
EXPECT_CALL(mockedUtils, getService(StrEq("/foo/bar"), _))
.Times(5)
.WillRepeatedly(Return("foo.bar"));
auto inPDRRepo = pldm_pdr_init();
auto numericEffecterPdrRepo = pldm_pdr_init();
Repo numericEffecterPDRs(numericEffecterPdrRepo);
auto event = sdeventplus::Event::get_default();
Handler handler(&mockedUtils, 0, nullptr, "./pdr_jsons/state_effecter/good",
inPDRRepo, nullptr, nullptr, nullptr, nullptr, nullptr,
event);
Repo inRepo(inPDRRepo);
getRepoByType(inRepo, numericEffecterPDRs, PLDM_NUMERIC_EFFECTER_PDR);
pdr_utils::PdrEntry e;
auto record4 = pdr::getRecordByHandle(numericEffecterPDRs, 4, e);
ASSERT_NE(record4, nullptr);
pldm_numeric_effecter_value_pdr* pdr =
reinterpret_cast<pldm_numeric_effecter_value_pdr*>(e.data);
EXPECT_EQ(pdr->hdr.type, PLDM_NUMERIC_EFFECTER_PDR);
uint16_t effecterId = 4;
uint8_t effecterDataSize{};
pldm::utils::PropertyValue dbusValue;
std::string propertyType;
auto rc = platform_numeric_effecter::getNumericEffecterData<
MockdBusHandler, Handler>(mockedUtils, handler, effecterId,
effecterDataSize, propertyType, dbusValue);
ASSERT_EQ(rc, 128);
pldm_pdr_destroy(inPDRRepo);
pldm_pdr_destroy(numericEffecterPdrRepo);
}
TEST(parseStateSensor, allScenarios)
{
// Sample state sensor with SensorID - 1, EntityType - Processor Module(67)
// State Set ID - Operational Running Status(11), Supported States - 3,4
std::vector<uint8_t> sample1PDR{
0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x17,
0x00, 0x00, 0x00, 0x01, 0x00, 0x43, 0x00, 0x01, 0x00,
0x00, 0x00, 0x00, 0x00, 0x01, 0x0b, 0x00, 0x01, 0x18};
const auto& [terminusHandle1, sensorID1, sensorInfo1] =
parseStateSensorPDR(sample1PDR);
const auto& [containerID1, entityType1, entityInstance1] =
std::get<0>(sensorInfo1);
const auto& states1 = std::get<1>(sensorInfo1);
CompositeSensorStates statesCmp1{{3u, 4u}};
ASSERT_EQ(le16toh(terminusHandle1), 0u);
ASSERT_EQ(le16toh(sensorID1), 1u);
ASSERT_EQ(le16toh(containerID1), 0u);
ASSERT_EQ(le16toh(entityType1), 67u);
ASSERT_EQ(le16toh(entityInstance1), 1u);
ASSERT_EQ(states1, statesCmp1);
// Sample state sensor with SensorID - 2, EntityType - System Firmware(31)
// State Set ID - Availability(2), Supported States - 3,4,9,10,11,13
std::vector<uint8_t> sample2PDR{
0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x17, 0x00,
0x00, 0x00, 0x02, 0x00, 0x1F, 0x00, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x01, 0x02, 0x00, 0x02, 0x18, 0x2E};
const auto& [terminusHandle2, sensorID2, sensorInfo2] =
parseStateSensorPDR(sample2PDR);
const auto& [containerID2, entityType2, entityInstance2] =
std::get<0>(sensorInfo2);
const auto& states2 = std::get<1>(sensorInfo2);
CompositeSensorStates statesCmp2{{3u, 4u, 9u, 10u, 11u, 13u}};
ASSERT_EQ(le16toh(terminusHandle2), 0u);
ASSERT_EQ(le16toh(sensorID2), 2u);
ASSERT_EQ(le16toh(containerID2), 0u);
ASSERT_EQ(le16toh(entityType2), 31u);
ASSERT_EQ(le16toh(entityInstance2), 1u);
ASSERT_EQ(states2, statesCmp2);
// Sample state sensor with SensorID - 3, EntityType - Virtual Machine
// Manager(33), Composite State Sensor -2 , State Set ID - Link State(33),
// Supported States - 1,2, State Set ID - Configuration State(15),
// Supported States - 1,2,3,4
std::vector<uint8_t> sample3PDR{
0x00, 0x00, 0x00, 0x00, 0x01, 0x04, 0x00, 0x00, 0x17, 0x00, 0x00,
0x00, 0x03, 0x00, 0x21, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00,
0x02, 0x21, 0x00, 0x01, 0x06, 0x0F, 0x00, 0x01, 0x1E};
const auto& [terminusHandle3, sensorID3, sensorInfo3] =
parseStateSensorPDR(sample3PDR);
const auto& [containerID3, entityType3, entityInstance3] =
std::get<0>(sensorInfo3);
const auto& states3 = std::get<1>(sensorInfo3);
CompositeSensorStates statesCmp3{{1u, 2u}, {1u, 2u, 3u, 4u}};
ASSERT_EQ(le16toh(terminusHandle3), 0u);
ASSERT_EQ(le16toh(sensorID3), 3u);
ASSERT_EQ(le16toh(containerID3), 1u);
ASSERT_EQ(le16toh(entityType3), 33u);
ASSERT_EQ(le16toh(entityInstance3), 2u);
ASSERT_EQ(states3, statesCmp3);
}
TEST(StateSensorHandler, allScenarios)
{
using namespace pldm::responder::events;
StateSensorHandler handler{"./event_jsons/good"};
constexpr uint8_t eventState0 = 0;
constexpr uint8_t eventState1 = 1;
constexpr uint8_t eventState2 = 2;
constexpr uint8_t eventState3 = 3;
// Event Entry 1
{
StateSensorEntry entry{1, 64, 1, 0, 1, false};
const auto& [dbusMapping, eventStateMap] = handler.getEventInfo(entry);
DBusMapping mapping{"/xyz/abc/def",
"xyz.openbmc_project.example1.value", "value1",
"string"};
ASSERT_EQ(mapping == dbusMapping, true);
const auto& propValue0 = eventStateMap.at(eventState0);
const auto& propValue1 = eventStateMap.at(eventState1);
const auto& propValue2 = eventStateMap.at(eventState2);
PropertyValue value0{std::in_place_type<std::string>,
"xyz.openbmc_project.State.Normal"};
PropertyValue value1{std::in_place_type<std::string>,
"xyz.openbmc_project.State.Critical"};
PropertyValue value2{std::in_place_type<std::string>,
"xyz.openbmc_project.State.Fatal"};
ASSERT_EQ(value0 == propValue0, true);
ASSERT_EQ(value1 == propValue1, true);
ASSERT_EQ(value2 == propValue2, true);
}
// Event Entry 2
{
StateSensorEntry entry{1, 64, 1, 1, 1, false};
const auto& [dbusMapping, eventStateMap] = handler.getEventInfo(entry);
DBusMapping mapping{"/xyz/abc/def",
"xyz.openbmc_project.example2.value", "value2",
"uint8_t"};
ASSERT_EQ(mapping == dbusMapping, true);
const auto& propValue0 = eventStateMap.at(eventState2);
const auto& propValue1 = eventStateMap.at(eventState3);
PropertyValue value0{std::in_place_type<uint8_t>, 9};
PropertyValue value1{std::in_place_type<uint8_t>, 10};
ASSERT_EQ(value0 == propValue0, true);
ASSERT_EQ(value1 == propValue1, true);
}
// Event Entry 3
{
StateSensorEntry entry{2, 67, 2, 0, 1, false};
const auto& [dbusMapping, eventStateMap] = handler.getEventInfo(entry);
DBusMapping mapping{"/xyz/abc/ghi",
"xyz.openbmc_project.example3.value", "value3",
"bool"};
ASSERT_EQ(mapping == dbusMapping, true);
const auto& propValue0 = eventStateMap.at(eventState0);
const auto& propValue1 = eventStateMap.at(eventState1);
PropertyValue value0{std::in_place_type<bool>, false};
PropertyValue value1{std::in_place_type<bool>, true};
ASSERT_EQ(value0 == propValue0, true);
ASSERT_EQ(value1 == propValue1, true);
}
// Event Entry 4
{
StateSensorEntry entry{2, 67, 2, 0, 2, false};
const auto& [dbusMapping, eventStateMap] = handler.getEventInfo(entry);
DBusMapping mapping{"/xyz/abc/jkl",
"xyz.openbmc_project.example4.value", "value4",
"string"};
ASSERT_EQ(mapping == dbusMapping, true);
const auto& propValue0 = eventStateMap.at(eventState0);
const auto& propValue1 = eventStateMap.at(eventState1);
const auto& propValue2 = eventStateMap.at(eventState2);
PropertyValue value0{std::in_place_type<std::string>, "Enabled"};
PropertyValue value1{std::in_place_type<std::string>, "Disabled"};
PropertyValue value2{std::in_place_type<std::string>, "Auto"};
ASSERT_EQ(value0 == propValue0, true);
ASSERT_EQ(value1 == propValue1, true);
ASSERT_EQ(value2 == propValue2, true);
}
// Event Entry 5
{
StateSensorEntry entry{0xFFFF, 120, 2, 0, 2, true};
const auto& [dbusMapping, eventStateMap] = handler.getEventInfo(entry);
DBusMapping mapping{"/xyz/abc/mno",
"xyz.openbmc_project.example5.value", "value5",
"string"};
ASSERT_EQ(mapping == dbusMapping, true);
const auto& propValue0 = eventStateMap.at(eventState0);
const auto& propValue1 = eventStateMap.at(eventState1);
const auto& propValue2 = eventStateMap.at(eventState2);
PropertyValue value0{std::in_place_type<std::string>, "Enabled"};
PropertyValue value1{std::in_place_type<std::string>, "Disabled"};
PropertyValue value2{std::in_place_type<std::string>, "Auto"};
ASSERT_EQ(value0 == propValue0, true);
ASSERT_EQ(value1 == propValue1, true);
ASSERT_EQ(value2 == propValue2, true);
}
// Event Entry 6
{
StateSensorEntry entry{10, 120, 2, 0, 2, true};
const auto& [dbusMapping, eventStateMap] = handler.getEventInfo(entry);
DBusMapping mapping{"/xyz/abc/opk",
"xyz.openbmc_project.example6.value", "value6",
"string"};
ASSERT_EQ(mapping == dbusMapping, true);
const auto& propValue0 = eventStateMap.at(eventState0);
const auto& propValue1 = eventStateMap.at(eventState1);
const auto& propValue2 = eventStateMap.at(eventState2);
PropertyValue value0{std::in_place_type<std::string>, "Enabled"};
PropertyValue value1{std::in_place_type<std::string>, "Disabled"};
PropertyValue value2{std::in_place_type<std::string>, "Auto"};
ASSERT_EQ(value0 == propValue0, true);
ASSERT_EQ(value1 == propValue1, true);
ASSERT_EQ(value2 == propValue2, true);
}
// Event Entry 7
{
StateSensorEntry entry{10, 120, 2, 0, 2, false};
const auto& [dbusMapping, eventStateMap] = handler.getEventInfo(entry);
DBusMapping mapping{"/xyz/abc/opk",
"xyz.openbmc_project.example6.value", "value6",
"string"};
ASSERT_EQ(mapping == dbusMapping, true);
const auto& propValue0 = eventStateMap.at(eventState0);
const auto& propValue1 = eventStateMap.at(eventState1);
const auto& propValue2 = eventStateMap.at(eventState2);
PropertyValue value0{std::in_place_type<std::string>, "Enabled"};
PropertyValue value1{std::in_place_type<std::string>, "Disabled"};
PropertyValue value2{std::in_place_type<std::string>, "Auto"};
ASSERT_EQ(value0 == propValue0, true);
ASSERT_EQ(value1 == propValue1, true);
ASSERT_EQ(value2 == propValue2, true);
}
// Invalid Entry
{
StateSensorEntry entry{0, 0, 0, 0, 1, false};
ASSERT_THROW(handler.getEventInfo(entry), std::out_of_range);
}
}
TEST(TerminusLocatorPDR, BMCTerminusLocatorPDR)
{
auto inPDRRepo = pldm_pdr_init();
auto outPDRRepo = pldm_pdr_init();
Repo outRepo(outPDRRepo);
MockdBusHandler mockedUtils;
auto event = sdeventplus::Event::get_default();
Handler handler(&mockedUtils, 0, nullptr, "", inPDRRepo, nullptr, nullptr,
nullptr, nullptr, nullptr, event);
Repo inRepo(inPDRRepo);
getRepoByType(inRepo, outRepo, PLDM_TERMINUS_LOCATOR_PDR);
// 1 BMC terminus locator PDR in the PDR repository
ASSERT_EQ(outRepo.getRecordCount(), 1);
pdr_utils::PdrEntry entry;
auto record = pdr::getRecordByHandle(outRepo, 1, entry);
ASSERT_NE(record, nullptr);
auto pdr = reinterpret_cast<const pldm_terminus_locator_pdr*>(entry.data);
EXPECT_EQ(pdr->hdr.record_handle, 1);
EXPECT_EQ(pdr->hdr.version, 1);
EXPECT_EQ(pdr->hdr.type, PLDM_TERMINUS_LOCATOR_PDR);
EXPECT_EQ(pdr->hdr.record_change_num, 0);
EXPECT_EQ(pdr->hdr.length,
sizeof(pldm_terminus_locator_pdr) - sizeof(pldm_pdr_hdr));
EXPECT_EQ(pdr->terminus_handle, TERMINUS_HANDLE);
EXPECT_EQ(pdr->validity, PLDM_TL_PDR_VALID);
EXPECT_EQ(pdr->tid, TERMINUS_ID);
EXPECT_EQ(pdr->container_id, 0);
EXPECT_EQ(pdr->terminus_locator_type, PLDM_TERMINUS_LOCATOR_TYPE_MCTP_EID);
EXPECT_EQ(pdr->terminus_locator_value_size,
sizeof(pldm_terminus_locator_type_mctp_eid));
auto locatorValue =
reinterpret_cast<const pldm_terminus_locator_type_mctp_eid*>(
pdr->terminus_locator_value);
EXPECT_EQ(locatorValue->eid, BmcMctpEid);
pldm_pdr_destroy(inPDRRepo);
pldm_pdr_destroy(outPDRRepo);
}
TEST(getStateSensorReadingsHandler, testGoodRequest)
{
MockdBusHandler mockedUtils;
EXPECT_CALL(mockedUtils, getService(StrEq("/foo/bar"), _))
.Times(1)
.WillRepeatedly(Return("foo.bar"));
auto inPDRRepo = pldm_pdr_init();
auto outPDRRepo = pldm_pdr_init();
Repo outRepo(outPDRRepo);
auto event = sdeventplus::Event::get_default();
Handler handler(&mockedUtils, 0, nullptr, "./pdr_jsons/state_sensor/good",
inPDRRepo, nullptr, nullptr, nullptr, nullptr, nullptr,
event);
Repo inRepo(inPDRRepo);
getRepoByType(inRepo, outRepo, PLDM_STATE_SENSOR_PDR);
pdr_utils::PdrEntry e;
auto record = pdr::getRecordByHandle(outRepo, 2, e);
ASSERT_NE(record, nullptr);
pldm_state_sensor_pdr* pdr =
reinterpret_cast<pldm_state_sensor_pdr*>(e.data);
EXPECT_EQ(pdr->hdr.type, PLDM_STATE_SENSOR_PDR);
std::vector<get_sensor_state_field> stateField;
uint8_t compSensorCnt{};
uint8_t sensorRearmCnt = 1;
MockdBusHandler handlerObj;
EXPECT_CALL(handlerObj,
getDbusPropertyVariant(StrEq("/foo/bar"), StrEq("propertyName"),
StrEq("xyz.openbmc_project.Foo.Bar")))
.WillOnce(Return(
PropertyValue(std::string("xyz.openbmc_project.Foo.Bar.V0"))));
EventStates cache = {PLDM_SENSOR_NORMAL};
pldm::stateSensorCacheMaps sensorCache;
sensorCache.emplace(0x1, cache);
auto rc = platform_state_sensor::getStateSensorReadingsHandler<
MockdBusHandler, Handler>(handlerObj, handler, 0x1, sensorRearmCnt,
compSensorCnt, stateField, sensorCache);
ASSERT_EQ(rc, 0);
ASSERT_EQ(compSensorCnt, 1);
ASSERT_EQ(stateField[0].sensor_op_state, PLDM_SENSOR_UNAVAILABLE);
ASSERT_EQ(stateField[0].present_state, PLDM_SENSOR_NORMAL);
ASSERT_EQ(stateField[0].previous_state, PLDM_SENSOR_NORMAL);
ASSERT_EQ(stateField[0].event_state, PLDM_SENSOR_UNKNOWN);
pldm_pdr_destroy(inPDRRepo);
pldm_pdr_destroy(outPDRRepo);
}
TEST(getStateSensorReadingsHandler, testBadRequest)
{
MockdBusHandler mockedUtils;
EXPECT_CALL(mockedUtils, getService(StrEq("/foo/bar"), _))
.Times(1)
.WillRepeatedly(Return("foo.bar"));
auto inPDRRepo = pldm_pdr_init();
auto outPDRRepo = pldm_pdr_init();
Repo outRepo(outPDRRepo);
auto event = sdeventplus::Event::get_default();
Handler handler(&mockedUtils, 0, nullptr, "./pdr_jsons/state_sensor/good",
inPDRRepo, nullptr, nullptr, nullptr, nullptr, nullptr,
event);
Repo inRepo(inPDRRepo);
getRepoByType(inRepo, outRepo, PLDM_STATE_SENSOR_PDR);
pdr_utils::PdrEntry e;
auto record = pdr::getRecordByHandle(outRepo, 2, e);
ASSERT_NE(record, nullptr);
pldm_state_sensor_pdr* pdr =
reinterpret_cast<pldm_state_sensor_pdr*>(e.data);
EXPECT_EQ(pdr->hdr.type, PLDM_STATE_SENSOR_PDR);
std::vector<get_sensor_state_field> stateField;
uint8_t compSensorCnt{};
uint8_t sensorRearmCnt = 3;
MockdBusHandler handlerObj;
EventStates cache = {PLDM_SENSOR_NORMAL};
pldm::stateSensorCacheMaps sensorCache;
sensorCache.emplace(0x1, cache);
auto rc = platform_state_sensor::getStateSensorReadingsHandler<
MockdBusHandler, Handler>(handlerObj, handler, 0x1, sensorRearmCnt,
compSensorCnt, stateField, sensorCache);
ASSERT_EQ(rc, PLDM_PLATFORM_REARM_UNAVAILABLE_IN_PRESENT_STATE);
pldm_pdr_destroy(inPDRRepo);
pldm_pdr_destroy(outPDRRepo);
}