blob: dff7bcca2bba3feeaf1cf965b0e6d022104fd3a0 [file]
#include "processor.hpp"
#include <filesystem>
#include <memory>
#include <string>
#include <utility>
#include <gtest/gtest.h>
#include "async_resp.hpp"
#include "dbus_utility.hpp"
#include "query.hpp"
#include "external_storer.hpp"
#include "test/redfish-core/lib/snapshot_fixture.hpp"
#include <nlohmann/json.hpp>
#include "managed_store.hpp"
#include "managed_store_types.hpp"
#include "test/g3/mock_managed_store.hpp"
#include "test/g3/mock_managed_store_test.hpp"
#include "sdbusplus/message/native_types.hpp"
namespace redfish {
namespace {
using ::dbus::utility::DBusInteracesMap;
using ::dbus::utility::DBusPropertiesMap;
using ::dbus::utility::DbusVariantType;
using ::dbus::utility::MapperGetSubTreePathsResponse;
using ::dbus::utility::MapperGetSubTreeResponse;
using ::dbus::utility::MapperServiceMap;
using ::managedStore::KeyType;
using ::managedStore::ManagedType;
using ::managedStore::ValueType;
class ProcessorSnapshotFixture : public SnapshotFixture {
protected:
static void SetUpTestSuite() {
SnapshotFixture::SetUpTestSuite();
const_cast<std::filesystem::path&>(external_storer::defPathPrefix) =
"/tmp/bmcweb";
}
};
TEST(ProcessorTest, IsValidSystemServicePair) {
// Positive test cases
EXPECT_TRUE(isValidSystemServicePair("system", "xyz.openbmc_project.pldm"));
EXPECT_TRUE(isValidSystemServicePair("system1", "xyz.openbmc_project.pldm0"));
EXPECT_TRUE(isValidSystemServicePair("system2", "xyz.openbmc_project.pldm1"));
// Negative test cases
EXPECT_FALSE(
isValidSystemServicePair("system1", "xyz.openbmc_project.pldm1"));
EXPECT_FALSE(
isValidSystemServicePair("system3", "xyz.openbmc_project.pldm0"));
EXPECT_FALSE(
isValidSystemServicePair("system1", "xyz.openbmc_project.pldm.invalid"));
EXPECT_FALSE(isValidSystemServicePair("", "xyz.openbmc_project.pldm0"));
EXPECT_FALSE(isValidSystemServicePair("system1", ""));
}
MapperGetSubTreeResponse CreateMapperGetSubTreeResponse() {
return MapperGetSubTreeResponse({std::make_pair(
"/xyz/openbmc_project/pldm/4/effecter/power/SOC_TDP_4",
MapperServiceMap({{"xyz.openbmc_project.pldm",
{
"xyz.openbmc_project.Effecter.Value",
"xyz.openbmc_project.Effecter.SetNumericEffecter",
"xyz.openbmc_project.State.Decorator.Availability",
}}}))});
}
TEST_F(SnapshotFixture_Platform5_Config0, GetProcessorTest) {
handleProcessorGet(app_, CreateRequest(), share_async_resp_, "system",
"cpu0");
RunIoUntilDone();
nlohmann::json& json = share_async_resp_->res.jsonValue;
EXPECT_EQ(json["@odata.id"].get<std::string>(),
"/redfish/v1/Systems/system/Processors/cpu0");
EXPECT_EQ(json["Name"].get<std::string>(), "Processor");
EXPECT_EQ(json["Id"].get<std::string>(), "cpu0");
// cores and threads
EXPECT_EQ(json["TotalCores"].get<int>(), 128);
EXPECT_EQ(json["TotalThreads"].get<int>(), 256);
EXPECT_EQ(json["TotalEnabledCores"].get<int>(), 128);
EXPECT_EQ(share_async_resp_->res.result(), boost::beast::http::status::ok);
}
TEST_F(SnapshotFixture, GetProcessorMaxTDP) {
const std::string processorId = "cpu0";
const std::string systemName = "system";
const std::string pldmService = "xyz.openbmc_project.pldm";
const std::string effecterPath =
"/xyz/openbmc_project/pldm/4/effecter/power/SOC_TDP_4";
const double tdpValue = 125.0;
KeyType keySubtree(ManagedType::kManagedSubtree, "/xyz/openbmc_project/pldm",
0, {"xyz.openbmc_project.Effecter.Value"});
std::shared_ptr<ValueType> mockedSubtree =
CreateValueType(CreateMapperGetSubTreeResponse());
EXPECT_TRUE(dynamic_cast<managedStore::MockSerializedManagedObjectStore*>(
managedStore::GetManagedObjectStore())
->upsertMockObjectIntoManagedStore(keySubtree, mockedSubtree)
.ok());
std::shared_ptr<ValueType> tdp_test_value =
CreateValueType(DbusVariantType(tdpValue));
// Test case 1: Correct property "Value" exists
KeyType pldmKey(ManagedType::kManagedProperty, pldmService,
sdbusplus::message::object_path(effecterPath),
"xyz.openbmc_project.Effecter.Value", "Value");
EXPECT_TRUE(dynamic_cast<managedStore::MockSerializedManagedObjectStore*>(
managedStore::GetManagedObjectStore())
->upsertMockObjectIntoManagedStore(pldmKey, tdp_test_value)
.ok());
handleProcessorGet(app_, CreateRequest(), share_async_resp_, systemName,
processorId);
RunIoUntilDone();
nlohmann::json& json = share_async_resp_->res.jsonValue;
ASSERT_TRUE(json.contains("MaxTDPWatts"));
EXPECT_EQ(json["MaxTDPWatts"], tdpValue);
EXPECT_EQ(share_async_resp_->res.result(), boost::beast::http::status::ok);
// Test case 2: Evict the key and make sure we don't see the property
ASSERT_TRUE(dynamic_cast<managedStore::MockSerializedManagedObjectStore*>(
managedStore::GetManagedObjectStore())
->evictMockObjectFromManagedStore(pldmKey)
.ok());
ASSERT_TRUE(dynamic_cast<managedStore::MockSerializedManagedObjectStore*>(
managedStore::GetManagedObjectStore())
->evictMockObjectFromManagedStore(keySubtree)
.ok());
share_async_resp_->res.clear();
handleProcessorGet(app_, CreateRequest(), share_async_resp_, systemName,
processorId);
RunIoUntilDone();
ASSERT_FALSE(json.contains("MaxTDPWatts"));
EXPECT_EQ(share_async_resp_->res.result(), boost::beast::http::status::ok);
// Test case 3: Insert the key again with an incorrect property name "Data"
// instead of "Value"
pldmKey = KeyType(ManagedType::kManagedProperty, pldmService,
sdbusplus::message::object_path(effecterPath),
"xyz.openbmc_project.Effecter.Value", "Data");
EXPECT_TRUE(dynamic_cast<managedStore::MockSerializedManagedObjectStore*>(
managedStore::GetManagedObjectStore())
->upsertMockObjectIntoManagedStore(pldmKey, tdp_test_value)
.ok());
EXPECT_TRUE(dynamic_cast<managedStore::MockSerializedManagedObjectStore*>(
managedStore::GetManagedObjectStore())
->upsertMockObjectIntoManagedStore(keySubtree, mockedSubtree)
.ok());
share_async_resp_->res.clear();
handleProcessorGet(app_, CreateRequest(), share_async_resp_, systemName,
processorId);
RunIoUntilDone();
ASSERT_FALSE(json.contains("MaxTDPWatts"));
EXPECT_EQ(share_async_resp_->res.result(), boost::beast::http::status::ok);
// Create a mocked response with an empty service map.
// This will cause the code to log an error and continue,
// not setting the MaxTDPWatts property.
dbus::utility::MapperGetSubTreeResponse subtreeWithEmptyServiceMap(
{std::make_pair("/xyz/openbmc_project/pldm/4/effecter/power/SOC_TDP_4",
dbus::utility::MapperServiceMap({}))});
std::shared_ptr<ValueType> mockedSubtreeEmpty =
CreateValueType(std::move(subtreeWithEmptyServiceMap));
EXPECT_TRUE(
dynamic_cast<managedStore::MockSerializedManagedObjectStore*>(
managedStore::GetManagedObjectStore())
->upsertMockObjectIntoManagedStore(keySubtree, mockedSubtreeEmpty)
.ok());
share_async_resp_->res.clear();
handleProcessorGet(app_, CreateRequest(), share_async_resp_, systemName,
processorId);
RunIoUntilDone();
ASSERT_FALSE(json.contains("MaxTDPWatts"));
EXPECT_EQ(share_async_resp_->res.result(), boost::beast::http::status::ok);
}
TEST_F(ProcessorSnapshotFixture, GetProcessorMaxTDPInvalidServicePair) {
const std::string processorId = "cpu0";
const std::string systemName = "system"; // system expects pldm
const std::string pldmService =
"xyz.openbmc_project.pldm0"; // but we provide pldm0
const std::string effecterPath =
"/xyz/openbmc_project/pldm/4/effecter/power/SOC_TDP_4";
// This is the key for the getSubTree call in getProcessorMaxTDP
KeyType keySubtree(ManagedType::kManagedSubtree, "/xyz/openbmc_project/pldm",
0, {"xyz.openbmc_project.Effecter.Value"});
// Create a mocked response for getSubTree
dbus::utility::MapperGetSubTreeResponse mockSubtreeResponse(
{std::make_pair(effecterPath,
dbus::utility::MapperServiceMap(
{{pldmService, // This is the invalid service
{"xyz.openbmc_project.Effecter.Value"}}}))});
std::shared_ptr<ValueType> mockedSubtree =
CreateValueType(std::move(mockSubtreeResponse));
EXPECT_TRUE(dynamic_cast<managedStore::MockSerializedManagedObjectStore*>(
managedStore::GetManagedObjectStore())
->upsertMockObjectIntoManagedStore(keySubtree, mockedSubtree)
.ok());
// Call the handler
handleProcessorGet(app_, CreateRequest(), share_async_resp_, systemName,
processorId);
RunIoUntilDone();
// Check the response
nlohmann::json& json = share_async_resp_->res.jsonValue;
EXPECT_FALSE(json.contains("MaxTDPWatts"));
EXPECT_EQ(share_async_resp_->res.result(), boost::beast::http::status::ok);
}
TEST_F(ProcessorSnapshotFixture, GetProcessorAndStateLinkTest) {
KeyType key(ManagedType::kManagedSubtreePaths,
"/xyz/openbmc_project/inventory", 0,
{"xyz.openbmc_project.Inventory.Item.ProcessorState"});
MapperGetSubTreePathsResponse mockProcState = {
"/xyz/openbmc_project/inventory/system/processorstate/PROC1",
"/xyz/openbmc_project/inventory/system/processorstate/PROC2"};
ASSERT_TRUE(dynamic_cast<managedStore::MockSerializedManagedObjectStore*>(
managedStore::GetManagedObjectStore())
->upsertMockObjectIntoManagedStore(
key, managedStore::MockManagedStoreTest::CreateValueType(
std::move(mockProcState)))
.ok());
handleProcessorGet(app_, CreateRequest(), share_async_resp_, "system",
"cpu0");
RunIoUntilDone();
nlohmann::json& json = share_async_resp_->res.jsonValue;
EXPECT_EQ(json["@odata.id"].get<std::string>(),
"/redfish/v1/Systems/system/Processors/cpu0");
EXPECT_EQ(json["Name"].get<std::string>(), "Processor");
EXPECT_EQ(json["Id"].get<std::string>(), "cpu0");
EXPECT_TRUE(json.contains("/Oem/Google/ProcessorStates"_json_pointer));
auto processorStates = json["Oem"]["Google"]["ProcessorStates"];
EXPECT_EQ(processorStates[0]["@odata.id"],
"/redfish/v1/Systems/system/Processors/cpu0/Oem/Google/"
"ProcessorStates/PROC1");
EXPECT_FALSE(processorStates[0].contains("Id"))
<< "Processor State got expanded at level 0";
EXPECT_EQ(processorStates[1]["@odata.id"],
"/redfish/v1/Systems/system/Processors/cpu0/Oem/Google/"
"ProcessorStates/PROC2");
EXPECT_FALSE(processorStates[1].contains("Id"))
<< "Processor State got expanded at level 0";
EXPECT_EQ(share_async_resp_->res.result(), boost::beast::http::status::ok);
}
TEST_F(ProcessorSnapshotFixture, GetProcessorCollectionWithExpandOneTest) {
KeyType key(ManagedType::kManagedSubtreePaths,
"/xyz/openbmc_project/inventory", 0,
{"xyz.openbmc_project.Inventory.Item.ProcessorState"});
MapperGetSubTreePathsResponse mockProcState = {
"/xyz/openbmc_project/inventory/system/processorstate/PROC1",
"/xyz/openbmc_project/inventory/system/processorstate/PROC2"};
ASSERT_TRUE(dynamic_cast<managedStore::MockSerializedManagedObjectStore*>(
managedStore::GetManagedObjectStore())
->upsertMockObjectIntoManagedStore(
key, managedStore::MockManagedStoreTest::CreateValueType(
std::move(mockProcState)))
.ok());
query_param::Query delegatedQuery;
delegatedQuery.expandLevel = 1;
delegatedQuery.expandType = query_param::ExpandType::Both;
handleProcessorCollection(share_async_resp_, delegatedQuery, "");
RunIoUntilDone();
EXPECT_TRUE(share_async_resp_->res.jsonValue.contains("Members"));
nlohmann::json& json = share_async_resp_->res.jsonValue["Members"][0];
EXPECT_EQ(json["@odata.id"].get<std::string>(),
"/redfish/v1/Systems/system/Processors/cpu0");
EXPECT_EQ(json["Name"].get<std::string>(), "Processor");
EXPECT_EQ(json["Id"].get<std::string>(), "cpu0");
EXPECT_TRUE(json.contains("/Oem/Google/ProcessorStates"_json_pointer));
auto processorStates = json["Oem"]["Google"]["ProcessorStates"];
EXPECT_EQ(processorStates[0]["@odata.id"],
"/redfish/v1/Systems/system/Processors/cpu0/Oem/Google/"
"ProcessorStates/PROC1");
EXPECT_FALSE(processorStates[0].contains("Id"))
<< "Processor State got expanded at level 0";
EXPECT_EQ(processorStates[1]["@odata.id"],
"/redfish/v1/Systems/system/Processors/cpu0/Oem/Google/"
"ProcessorStates/PROC2");
EXPECT_FALSE(processorStates[1].contains("Id"))
<< "Processor State got expanded at level 0";
EXPECT_EQ(share_async_resp_->res.result(), boost::beast::http::status::ok);
}
void mockProcessorState(const std::string& processorState) {
KeyType key(ManagedType::kManagedSubtreePaths,
"/xyz/openbmc_project/inventory", 0,
{"xyz.openbmc_project.Inventory.Item.ProcessorState"});
MapperGetSubTreePathsResponse mockProcState = {
"/xyz/openbmc_project/inventory/system/processorstate/" + processorState};
ASSERT_TRUE(dynamic_cast<managedStore::MockSerializedManagedObjectStore*>(
managedStore::GetManagedObjectStore())
->upsertMockObjectIntoManagedStore(
key, managedStore::MockManagedStoreTest::CreateValueType(
std::move(mockProcState)))
.ok());
managedStore::KeyType presentKey(
managedStore::ManagedType::kManagedProperty,
"xyz.openbmc_project.EntityManager",
{"/xyz/openbmc_project/inventory/system/processorstate/" +
processorState},
"xyz.openbmc_project.Inventory.Item", "Present");
std::shared_ptr<ValueType> mockPresent =
managedStore::MockManagedStoreTest::CreateValueType(std::move(true));
ASSERT_TRUE(dynamic_cast<managedStore::MockSerializedManagedObjectStore*>(
managedStore::GetManagedObjectStore())
->upsertMockObjectIntoManagedStore(presentKey, mockPresent)
.ok());
}
TEST_F(ProcessorSnapshotFixture, GetProcessorCollectionExpand2Test) {
mockProcessorState("PROC1");
for (int i = 2; i <= 6; i++) {
share_async_resp_ = std::make_shared<bmcweb::AsyncResp>();
query_param::Query delegatedQuery;
delegatedQuery.expandLevel = i;
delegatedQuery.expandType = query_param::ExpandType::Both;
handleProcessorCollection(share_async_resp_, delegatedQuery, "");
RunIoUntilDone();
EXPECT_TRUE(share_async_resp_->res.jsonValue.contains("Members"));
nlohmann::json& json = share_async_resp_->res.jsonValue["Members"][0];
EXPECT_TRUE(json.contains("/Oem/Google/ProcessorStates"_json_pointer));
auto processorStates = json["Oem"]["Google"]["ProcessorStates"];
EXPECT_EQ(processorStates[0]["@odata.id"],
"/redfish/v1/Systems/system/Processors/cpu0/Oem/Google/"
"ProcessorStates/PROC1");
EXPECT_TRUE(processorStates[0].contains("Id"))
<< "Processor State did not expand at level 2";
EXPECT_EQ(processorStates[0]["Id"], "PROC1");
EXPECT_EQ(processorStates[0]["Name"], "Processor");
EXPECT_EQ(processorStates[0]["@odata.type"],
"#GoogleProcessorState.GoogleProcessorState");
EXPECT_EQ(processorStates[0]["Status"]["State"], "Enabled");
EXPECT_EQ(share_async_resp_->res.result(), boost::beast::http::status::ok);
}
}
TEST_F(ProcessorSnapshotFixture, GetProcessorStateTest) {
mockProcessorState("PROC1");
handleGetProcessorState(app_, CreateRequest(), share_async_resp_, "system",
"cpu0", "PROC1");
RunIoUntilDone();
nlohmann::json& json = share_async_resp_->res.jsonValue;
EXPECT_EQ(json["@odata.id"],
"/redfish/v1/Systems/system/Processors/cpu0/Oem/Google/"
"ProcessorStates/PROC1");
EXPECT_EQ(json["Id"], "PROC1");
EXPECT_EQ(json["Name"], "Processor");
EXPECT_EQ(json["@odata.type"], "#GoogleProcessorState.GoogleProcessorState");
EXPECT_EQ(json["Status"]["State"], "Enabled");
EXPECT_EQ(share_async_resp_->res.result(), boost::beast::http::status::ok);
}
} // namespace
} // namespace redfish