| #include "processor.hpp" |
| #include "async_resp.hpp" |
| #include "dbus_utility.hpp" |
| #include "gtest/gtest.h" |
| #include "managed_store_types.hpp" |
| #include "snapshot_fixture.hpp" |
| #include <nlohmann/json.hpp> |
| #include <gmock/gmock.h> |
| #include <gtest/gtest.h> |
| |
| namespace redfish |
| { |
| namespace |
| { |
| |
| using ::dbus::utility::MapperGetSubTreePathsResponse; |
| using ::dbus::utility::MapperGetSubTreeResponse; |
| using ::managedStore::KeyType; |
| using ::managedStore::ManagedType; |
| using ::managedStore::ValueType; |
| using ::dbus::utility::DbusVariantType; |
| using ::dbus::utility::DBusPropertiesMap; |
| using ::dbus::utility::DBusInteracesMap; |
| using ::dbus::utility::MapperServiceMap; |
| |
| 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( |
| 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(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(managedStore::GetManagedObjectStore() |
| ->evictMockObjectFromManagedStore(pldmKey) |
| .ok()); |
| ASSERT_TRUE(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(managedStore::GetManagedObjectStore() |
| ->upsertMockObjectIntoManagedStore(pldmKey, tdp_test_value) |
| .ok()); |
| EXPECT_TRUE( |
| 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( |
| 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(SnapshotFixture, 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(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(SnapshotFixture, 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( |
| 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(SnapshotFixture, 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( |
| 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( |
| 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(managedStore::GetManagedObjectStore() |
| ->upsertMockObjectIntoManagedStore(presentKey, mockPresent) |
| .ok()); |
| } |
| |
| TEST_F(SnapshotFixture, GetProcessorCollectionExpand2Test) |
| { |
| mockProcessorState("PROC1"); |
| for (int i = 2; i <= 6; i++) |
| { |
| 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(SnapshotFixture, 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 |