blob: b88a634516c726f3bc5ab3a1c47329dfbb673903 [file]
#include "network_adapter.hpp"
#include <cstdint>
#include <memory>
#include <vector>
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "http_response.hpp"
#include "dbus_utility.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::ManagedObjectType;
using ::dbus::utility::MapperGetSubTreePathsResponse;
using ::managedStore::KeyType;
using ::managedStore::ManagedType;
using ::managedStore::ValueType;
using ::testing::Contains;
MapperGetSubTreePathsResponse CreateMockNcsiSubTree() {
return MapperGetSubTreePathsResponse(
{"/xyz/openbmc_project/inventory/system/cable/NcsiCable/ncsi"});
}
class NetworkAdapterTest : public SnapshotFixture {
protected:
void SetUp() override {
SnapshotFixture::SetUp();
::milotic::authz::BmcWebAuthorizerSingleton::GetInstance()
.SetHasBmcDirectEthernet(false);
}
void TearDown() override {
::milotic::authz::BmcWebAuthorizerSingleton::GetInstance()
.SetHasBmcDirectEthernet(false);
SnapshotFixture::TearDown();
}
};
TEST_F(NetworkAdapterTest, GetNetworkAdaptersReturnsCorrectResponse) {
handleChassisNetworkAdapterCollectionGetSysfs(share_async_resp_,
"chassis1V2ND");
nlohmann::json& json = share_async_resp_->res.jsonValue;
EXPECT_EQ(json["@odata.id"],
"/redfish/v1/Chassis/chassis1V2ND/NetworkAdapters");
EXPECT_EQ(json["@odata.type"],
"#NetworkAdapterCollection.NetworkAdapterCollection");
EXPECT_EQ(json["Name"],
"Network adapter Collection for chassis chassis1V2ND");
EXPECT_THAT(json["Members"],
Contains(nlohmann::json(
{{"@odata.id",
"/redfish/v1/Chassis/chassis1V2ND/NetworkAdapters/0"}})));
EXPECT_EQ(json["Members@odata.count"], 1);
}
TEST_F(NetworkAdapterTest, GetNetworkAdapterReturnsCorrectResponse) {
handleChassisNetworkAdapterGetSysfs(share_async_resp_, "chassis1V2ND", "0");
nlohmann::json& json = share_async_resp_->res.jsonValue;
EXPECT_EQ(json["@odata.id"],
"/redfish/v1/Chassis/chassis1V2ND/NetworkAdapters/0");
EXPECT_EQ(json["@odata.type"], "#NetworkAdapter.NetworkAdapter");
EXPECT_EQ(json["Name"], "Network adapter");
EXPECT_EQ(json["Ports"]["@odata.id"],
"/redfish/v1/Chassis/chassis1V2ND/NetworkAdapters/0/Ports");
}
TEST_F(NetworkAdapterTest, GetPortCollectionReturnsCorrectResponse) {
handleNetworkPortCollectionGetSysfs(share_async_resp_, "chassis1V2ND", "0");
nlohmann::json& json = share_async_resp_->res.jsonValue;
EXPECT_EQ(json["@odata.id"],
"/redfish/v1/Chassis/chassis1V2ND/NetworkAdapters/0/Ports");
EXPECT_EQ(json["@odata.type"], "#PortCollection.PortCollection");
EXPECT_THAT(json["Members"],
Contains(nlohmann::json({{"@odata.id",
"/redfish/v1/Chassis/chassis1V2ND/"
"NetworkAdapters/0/Ports/ncsi"}})));
EXPECT_THAT(json["Members"],
Contains(nlohmann::json({{"@odata.id",
"/redfish/v1/Chassis/chassis1V2ND/"
"NetworkAdapters/0/Ports/gusbem0"}})));
EXPECT_THAT(json["Members"],
Contains(nlohmann::json({{"@odata.id",
"/redfish/v1/Chassis/chassis1V2ND/"
"NetworkAdapters/0/Ports/front"}})));
EXPECT_THAT(
json["Members"],
Contains(nlohmann::json({{"@odata.id",
"/redfish/v1/Chassis/chassis1V2ND/"
"NetworkAdapters/0/Ports/enu1u1u1u1"}})));
EXPECT_EQ(json["Members@odata.count"], 4);
EXPECT_EQ(json["Name"], "Network ports");
}
TEST_F(NetworkAdapterTest, GetPortsReturnsCorrectResponse1) {
KeyType key(ManagedType::kManagedSubtreePaths,
"/xyz/openbmc_project/inventory/system/cable/", 0,
{"xyz.openbmc_project.Configuration.Port"});
std::shared_ptr<ValueType> mockNcsiSubTreeResponse =
managedStore::MockManagedStoreTest::CreateValueType(
CreateMockNcsiSubTree());
ASSERT_TRUE(
dynamic_cast<managedStore::MockSerializedManagedObjectStore*>(
managedStore::GetManagedObjectStore())
->upsertMockObjectIntoManagedStore(key, mockNcsiSubTreeResponse)
.ok());
handleNetworkPortGetSysfs(share_async_resp_, "chassis1V2ND", "0", "ncsi");
RunIoUntilDone();
nlohmann::json& json = share_async_resp_->res.jsonValue;
EXPECT_EQ(json["@odata.id"],
"/redfish/v1/Chassis/chassis1V2ND/NetworkAdapters/0/Ports/ncsi");
EXPECT_EQ(json["@odata.type"], "#Port.Port");
EXPECT_EQ(json["Id"], "ncsi");
EXPECT_EQ(json["CurrentSpeedGbps"], 0.1);
EXPECT_EQ(json["Name"], "ncsi");
EXPECT_THAT(json["Ethernet"]["AssociatedMACAddresses"],
Contains("24:95:2f:8f:18:0c"));
EXPECT_EQ(json["Ethernet"]["AssociatedMACAddresses"].size(), 1);
EXPECT_EQ(json["LinkState"], "Enabled");
EXPECT_EQ(json["LinkStatus"], "LinkUp");
EXPECT_EQ(json["Oem"]["Google"]["ConnectionPath"], "SIDE");
EXPECT_EQ(json["Location"]["PartLocation"]["ServiceLabel"], "NCSI");
EXPECT_EQ(json["Location"]["Oem"]["Google"]["Devpath"], "/phys/NCSI");
EXPECT_EQ(
json["Metrics"]["@odata.id"],
"/redfish/v1/Chassis/chassis1V2ND/NetworkAdapters/0/Ports/ncsi/Metrics");
}
TEST_F(NetworkAdapterTest, GetPortsReturnsCorrectResponse2) {
handleNetworkPortGetSysfs(share_async_resp_, "chassis1V2ND", "0", "gusbem0");
RunIoUntilDone();
nlohmann::json& json = share_async_resp_->res.jsonValue;
EXPECT_EQ(json["@odata.id"],
"/redfish/v1/Chassis/chassis1V2ND/NetworkAdapters/0/Ports/gusbem0");
EXPECT_EQ(json["@odata.type"], "#Port.Port");
EXPECT_EQ(json["Id"], "gusbem0");
EXPECT_EQ(json["CurrentSpeedGbps"], 0.0);
EXPECT_EQ(json["Name"], "gusbem0");
EXPECT_THAT(json["Ethernet"]["AssociatedMACAddresses"],
Contains("3a:1b:f6:ef:56:62"));
EXPECT_EQ(json["Ethernet"]["AssociatedMACAddresses"].size(), 1);
EXPECT_EQ(json["LinkState"], "Enabled");
EXPECT_EQ(json["LinkStatus"], "LinkUp");
EXPECT_EQ(json["Metrics"]["@odata.id"],
"/redfish/v1/Chassis/chassis1V2ND/NetworkAdapters/0/Ports/gusbem0/"
"Metrics");
}
TEST_F(NetworkAdapterTest, GetPortsReturnsCorrectResponse3) {
::milotic::authz::BmcWebAuthorizerSingleton::GetInstance()
.SetHasBmcDirectEthernet(true);
KeyType key(
ManagedType::kManagedProperty, "xyz.openbmc_project.EntityManager",
sdbusplus::message::object_path(
"/xyz/openbmc_project/inventory/system/board/chassis1V2ND/BmcNet"),
"xyz.openbmc_project.Configuration.BmcNet", "LocationCode");
std::shared_ptr<ValueType> mockBmcNetLocation =
managedStore::MockManagedStoreTest::CreateValueType("1G_LAN");
ASSERT_TRUE(dynamic_cast<managedStore::MockSerializedManagedObjectStore*>(
managedStore::GetManagedObjectStore())
->upsertMockObjectIntoManagedStore(key, mockBmcNetLocation)
.ok());
handleNetworkPortGetSysfs(share_async_resp_, "chassis1V2ND", "0", "front");
RunIoUntilDone();
nlohmann::json& json = share_async_resp_->res.jsonValue;
EXPECT_EQ(json["@odata.id"],
"/redfish/v1/Chassis/chassis1V2ND/NetworkAdapters/0/Ports/front");
EXPECT_EQ(json["@odata.type"], "#Port.Port");
EXPECT_EQ(json["Id"], "front");
EXPECT_EQ(json["CurrentSpeedGbps"], 1);
EXPECT_EQ(json["Name"], "front");
EXPECT_THAT(json["Ethernet"]["AssociatedMACAddresses"],
Contains("24:95:2f:8f:18:0c"));
EXPECT_EQ(json["Ethernet"]["AssociatedMACAddresses"].size(), 1);
EXPECT_EQ(json["LinkState"], "Enabled");
EXPECT_EQ(json["LinkStatus"], "LinkUp");
EXPECT_EQ(json["Oem"]["Google"]["ConnectionPath"], "DIRECT");
EXPECT_EQ(json["Location"]["PartLocation"]["ServiceLabel"], "1G_LAN");
EXPECT_EQ(json["Location"]["Oem"]["Google"]["Devpath"],
"/phys/DC_SCM/1G_LAN");
EXPECT_EQ(
json["Metrics"]["@odata.id"],
"/redfish/v1/Chassis/chassis1V2ND/NetworkAdapters/0/Ports/front/Metrics");
}
TEST_F(NetworkAdapterTest,
GetPortsReturnsCorrectResponseWithoutDirectEthernetRole) {
::milotic::authz::BmcWebAuthorizerSingleton::GetInstance()
.SetHasBmcDirectEthernet(false);
KeyType key(
ManagedType::kManagedProperty, "xyz.openbmc_project.EntityManager",
sdbusplus::message::object_path(
"/xyz/openbmc_project/inventory/system/board/chassis1V2ND/BmcNet"),
"xyz.openbmc_project.Configuration.BmcNet", "LocationCode");
std::shared_ptr<ValueType> mockBmcNetLocation =
managedStore::MockManagedStoreTest::CreateValueType("1G_LAN");
ASSERT_TRUE(dynamic_cast<managedStore::MockSerializedManagedObjectStore*>(
managedStore::GetManagedObjectStore())
->upsertMockObjectIntoManagedStore(key, mockBmcNetLocation)
.ok());
handleNetworkPortGetSysfs(share_async_resp_, "chassis1V2ND", "0", "front");
RunIoUntilDone();
nlohmann::json& json = share_async_resp_->res.jsonValue;
EXPECT_EQ(json["@odata.id"],
"/redfish/v1/Chassis/chassis1V2ND/NetworkAdapters/0/Ports/front");
EXPECT_EQ(json["@odata.type"], "#Port.Port");
EXPECT_EQ(json["Id"], "front");
EXPECT_EQ(json["CurrentSpeedGbps"], 1);
EXPECT_EQ(json["Name"], "front");
EXPECT_THAT(json["Ethernet"]["AssociatedMACAddresses"],
Contains("24:95:2f:8f:18:0c"));
EXPECT_EQ(json["Ethernet"]["AssociatedMACAddresses"].size(), 1);
EXPECT_EQ(json["LinkState"], "Enabled");
EXPECT_EQ(json["LinkStatus"], "LinkUp");
EXPECT_FALSE(json.contains("Location"));
EXPECT_FALSE(json.contains("Oem"));
EXPECT_EQ(
json["Metrics"]["@odata.id"],
"/redfish/v1/Chassis/chassis1V2ND/NetworkAdapters/0/Ports/front/Metrics");
}
TEST_F(NetworkAdapterTest, GetPortsReturnsCorrectResponse4) {
auto* mockStore =
dynamic_cast<managedStore::MockSerializedManagedObjectStore*>(
managedStore::GetManagedObjectStore());
// Mock BmcNet Side Configuration for ConnectionPath
managedStore::KeyType bmcNetSideKey(
ManagedType::kManagedPropertyMap, "xyz.openbmc_project.EntityManager",
sdbusplus::message::object_path("/xyz/openbmc_project/inventory/system/"
"board/chassis1V2ND/enu1u1u1u1"),
"xyz.openbmc_project.Configuration.BmcNet_Side", "");
dbus::utility::DBusPropertiesMap bmcNetSideProperties;
bmcNetSideProperties.emplace_back(
"LocationCode", dbus::utility::DbusVariantType("SIDEBAND_LOC"));
bmcNetSideProperties.emplace_back(
"PartLocationContext",
dbus::utility::DbusVariantType("SIDEBAND_CONTEXT"));
EXPECT_TRUE(mockStore
->upsertMockObjectIntoManagedStore(
bmcNetSideKey,
managedStore::MockManagedStoreTest::CreateValueType(
bmcNetSideProperties))
.ok());
handleNetworkPortGetSysfs(share_async_resp_, "chassis1V2ND", "0",
"enu1u1u1u1");
RunIoUntilDone();
nlohmann::json& json = share_async_resp_->res.jsonValue;
EXPECT_EQ(json["Id"], "enu1u1u1u1");
EXPECT_EQ(json["Oem"]["Google"]["ConnectionPath"], "SIDEBAND");
EXPECT_EQ(json["Location"]["PartLocation"]["ServiceLabel"], "SIDEBAND_LOC");
EXPECT_EQ(json["Location"]["PartLocationContext"], "SIDEBAND_CONTEXT");
}
TEST_F(NetworkAdapterTest, GetNetworkPortMetricReturnsCorrectResponse1) {
handleNetworkPortMetricGetSysfs(share_async_resp_, "chassis1V2ND", "0",
"ncsi");
nlohmann::json& json = share_async_resp_->res.jsonValue;
EXPECT_EQ(
json["@odata.id"],
"/redfish/v1/Chassis/chassis1V2ND/NetworkAdapters/0/Ports/ncsi/Metrics");
EXPECT_EQ(json["@odata.type"], "#PortMetrics.PortMetrics");
EXPECT_EQ(json["Name"], "Network port metrics");
EXPECT_EQ(json["Oem"]["Google"]["Networking"]["CarrierChanges"], 1);
EXPECT_EQ(json["Oem"]["Google"]["Networking"]["RXCRCErrors"], 4);
EXPECT_EQ(json["Oem"]["Google"]["Networking"]["RXErrors"], 4);
EXPECT_EQ(json["Oem"]["Google"]["Networking"]["ReceivedPackets"], 3016523);
EXPECT_EQ(json["Oem"]["Google"]["Networking"]["ReceivedPacketsDropped"], 0);
}
TEST_F(NetworkAdapterTest, GetNetworkPortMetricReturnsCorrectResponse2) {
handleNetworkPortMetricGetSysfs(share_async_resp_, "chassis1V2ND", "0",
"gusbem0");
nlohmann::json& json = share_async_resp_->res.jsonValue;
EXPECT_EQ(json["@odata.id"],
"/redfish/v1/Chassis/chassis1V2ND/NetworkAdapters/0/Ports/gusbem0/"
"Metrics");
EXPECT_EQ(json["@odata.type"], "#PortMetrics.PortMetrics");
EXPECT_EQ(json["Name"], "Network port metrics");
EXPECT_EQ(json["Oem"]["Google"]["Networking"]["CarrierChanges"], 4);
EXPECT_EQ(json["Oem"]["Google"]["Networking"]["RXCRCErrors"], 0);
EXPECT_EQ(json["Oem"]["Google"]["Networking"]["RXErrors"], 0);
EXPECT_EQ(json["Oem"]["Google"]["Networking"]["ReceivedPackets"], 13218);
EXPECT_EQ(json["Oem"]["Google"]["Networking"]["ReceivedPacketsDropped"], 0);
}
TEST_F(NetworkAdapterTest, GetNetworkPortMetricReturnsCorrectResponse3) {
handleNetworkPortMetricGetSysfs(share_async_resp_, "chassis1V2ND", "0",
"front");
nlohmann::json& json = share_async_resp_->res.jsonValue;
EXPECT_EQ(
json["@odata.id"],
"/redfish/v1/Chassis/chassis1V2ND/NetworkAdapters/0/Ports/front/Metrics");
EXPECT_EQ(json["@odata.type"], "#PortMetrics.PortMetrics");
EXPECT_EQ(json["Name"], "Network port metrics");
EXPECT_EQ(json["Oem"]["Google"]["Networking"]["CarrierChanges"], 1);
EXPECT_EQ(json["Oem"]["Google"]["Networking"]["RXCRCErrors"], 0);
EXPECT_EQ(json["Oem"]["Google"]["Networking"]["RXErrors"], 0);
EXPECT_EQ(json["Oem"]["Google"]["Networking"]["ReceivedPackets"], 458937);
EXPECT_EQ(json["Oem"]["Google"]["Networking"]["ReceivedPacketsDropped"], 0);
}
TEST_F(NetworkAdapterTest, GetNetworkPortMetricDBusReturnsCorrectResponse) {
auto* mockStore =
dynamic_cast<managedStore::MockSerializedManagedObjectStore*>(
managedStore::GetManagedObjectStore());
// 1. Mock port Inventory SubTree
managedStore::KeyType portSubTreeKey(
ManagedType::kManagedSubtree, "/xyz/openbmc_project/inventory", 0,
{"xyz.openbmc_project.Inventory.Item.Port"});
dbus::utility::MapperGetSubTreeResponse portSubTree = {
{"/xyz/openbmc_project/inventory/system/chassis/chassis0/NetworkAdapters/"
"adapter0/Ports/Port_1",
{{"xyz.openbmc_project.NSM",
{"xyz.openbmc_project.Inventory.Item.Port"}}}}};
EXPECT_TRUE(
mockStore
->upsertMockObjectIntoManagedStore(
portSubTreeKey,
managedStore::MockManagedStoreTest::CreateValueType(portSubTree))
.ok());
// 2. Mock PortECC properties
managedStore::KeyType eccKey(
ManagedType::kManagedPropertyMap, "xyz.openbmc_project.NSM",
sdbusplus::message::object_path("/xyz/openbmc_project/inventory/system/"
"chassis/chassis0/NetworkAdapters/"
"adapter0/Ports/Port_1"),
"xyz.openbmc_project.Metrics.PortECC", "");
dbus::utility::DBusPropertiesMap eccProperties;
eccProperties.emplace_back("CorrectedBits",
dbus::utility::DbusVariantType(uint64_t{42}));
eccProperties.emplace_back("SymbolErrorRXBytes",
dbus::utility::DbusVariantType(uint64_t{7}));
std::vector<uint32_t> perLaneCounters = {10, 20, 30, 40};
eccProperties.emplace_back("RawErrorsPerLane",
dbus::utility::DbusVariantType(perLaneCounters));
EXPECT_TRUE(
mockStore
->upsertMockObjectIntoManagedStore(
eccKey, managedStore::MockManagedStoreTest::CreateValueType(
eccProperties))
.ok());
// 3. Mock PortPacketCounters properties
managedStore::KeyType packetKey(
ManagedType::kManagedPropertyMap, "xyz.openbmc_project.NSM",
sdbusplus::message::object_path("/xyz/openbmc_project/inventory/system/"
"chassis/chassis0/NetworkAdapters/"
"adapter0/Ports/Port_1"),
"xyz.openbmc_project.Metrics.PortPacketCounters", "");
dbus::utility::DBusPropertiesMap packetProperties;
packetProperties.emplace_back("RXBroadcastPkts",
dbus::utility::DbusVariantType(uint64_t{100}));
packetProperties.emplace_back("RXMulticastPkts",
dbus::utility::DbusVariantType(uint64_t{200}));
packetProperties.emplace_back("RXUnicastPkts",
dbus::utility::DbusVariantType(uint64_t{300}));
packetProperties.emplace_back("TXBroadcastPkts",
dbus::utility::DbusVariantType(uint64_t{400}));
packetProperties.emplace_back("TXMulticastPkts",
dbus::utility::DbusVariantType(uint64_t{500}));
packetProperties.emplace_back("TXUnicastPkts",
dbus::utility::DbusVariantType(uint64_t{600}));
EXPECT_TRUE(
mockStore
->upsertMockObjectIntoManagedStore(
packetKey, managedStore::MockManagedStoreTest::CreateValueType(
packetProperties))
.ok());
// 4. Mock EthPort properties
managedStore::KeyType ethKey(
ManagedType::kManagedPropertyMap, "xyz.openbmc_project.NSM",
sdbusplus::message::object_path("/xyz/openbmc_project/inventory/system/"
"chassis/chassis0/NetworkAdapters/"
"adapter0/Ports/Port_1"),
"xyz.openbmc_project.Metrics.EthPort", "");
dbus::utility::DBusPropertiesMap ethProperties;
ethProperties.emplace_back("RXFCSErrors",
dbus::utility::DbusVariantType(uint64_t{3}));
ethProperties.emplace_back("RXAlignmentErrors",
dbus::utility::DbusVariantType(uint64_t{1}));
ethProperties.emplace_back("PauseXOFFFramesReceived",
dbus::utility::DbusVariantType(uint64_t{5}));
EXPECT_TRUE(
mockStore
->upsertMockObjectIntoManagedStore(
ethKey, managedStore::MockManagedStoreTest::CreateValueType(
ethProperties))
.ok());
// 5. Mock IBPort properties
managedStore::KeyType ibKey(
ManagedType::kManagedPropertyMap, "xyz.openbmc_project.NSM",
sdbusplus::message::object_path("/xyz/openbmc_project/inventory/system/"
"chassis/chassis0/NetworkAdapters/"
"adapter0/Ports/Port_1"),
"xyz.openbmc_project.Metrics.IBPort", "");
dbus::utility::DBusPropertiesMap ibProperties;
ibProperties.emplace_back("BitErrorRate",
dbus::utility::DbusVariantType(double{1e-12}));
ibProperties.emplace_back("LinkDownCount",
dbus::utility::DbusVariantType(uint64_t{2}));
EXPECT_TRUE(
mockStore
->upsertMockObjectIntoManagedStore(
ibKey,
managedStore::MockManagedStoreTest::CreateValueType(ibProperties))
.ok());
// 6. Mock PortMetricsOem2 properties
managedStore::KeyType oem2Key(
ManagedType::kManagedPropertyMap, "xyz.openbmc_project.NSM",
sdbusplus::message::object_path("/xyz/openbmc_project/inventory/system/"
"chassis/chassis0/NetworkAdapters/"
"adapter0/Ports/Port_1"),
"xyz.openbmc_project.Metrics.PortMetricsOem2", "");
dbus::utility::DBusPropertiesMap oem2Properties;
oem2Properties.emplace_back(
"RXBytes", dbus::utility::DbusVariantType(uint64_t{1048576}));
oem2Properties.emplace_back(
"TXBytes", dbus::utility::DbusVariantType(uint64_t{2097152}));
EXPECT_TRUE(
mockStore
->upsertMockObjectIntoManagedStore(
oem2Key, managedStore::MockManagedStoreTest::CreateValueType(
oem2Properties))
.ok());
// 7. Mock PCIeECC properties
managedStore::KeyType pcieKey(
ManagedType::kManagedPropertyMap, "xyz.openbmc_project.NSM",
sdbusplus::message::object_path("/xyz/openbmc_project/inventory/system/"
"chassis/chassis0/NetworkAdapters/"
"adapter0/Ports/Port_1"),
"xyz.openbmc_project.PCIe.PCIeECC", "");
dbus::utility::DBusPropertiesMap pcieProperties;
pcieProperties.emplace_back("ceCount",
dbus::utility::DbusVariantType(uint64_t{9}));
pcieProperties.emplace_back("ueCount",
dbus::utility::DbusVariantType(uint64_t{0}));
EXPECT_TRUE(
mockStore
->upsertMockObjectIntoManagedStore(
pcieKey, managedStore::MockManagedStoreTest::CreateValueType(
pcieProperties))
.ok());
handleNetworkPortMetricGetDBus(share_async_resp_, "chassis0", "adapter0",
"Port_1");
RunIoUntilDone();
nlohmann::json& json = share_async_resp_->res.jsonValue;
EXPECT_EQ(
json["@odata.id"],
"/redfish/v1/Chassis/chassis0/NetworkAdapters/adapter0/Ports/Port_1/"
"Metrics");
EXPECT_EQ(json["@odata.type"], "#PortMetrics.v1_3_0.PortMetrics");
EXPECT_EQ(json["Name"], "Port_1 Metrics");
EXPECT_EQ(json["Id"], "Metrics");
EXPECT_EQ(json["CorrectableBitErrors"], 42);
EXPECT_EQ(json["SymbolErrors"], 7);
EXPECT_EQ(json["RXBroadcastPackets"], 100);
EXPECT_EQ(json["RXMulticastPackets"], 200);
EXPECT_EQ(json["RXUnicastPackets"], 300);
EXPECT_EQ(json["TXBroadcastPackets"], 400);
EXPECT_EQ(json["TXMulticastPackets"], 500);
EXPECT_EQ(json["TXUnicastPackets"], 600);
EXPECT_EQ(json["RXFCSErrors"], 3);
EXPECT_EQ(json["RXAlignmentErrors"], 1);
EXPECT_EQ(json["RXBytes"], 1048576);
EXPECT_EQ(json["TXBytes"], 2097152);
EXPECT_EQ(json["Oem"]["Google"]["TransceiverTelemetry"]["FECCorrectedCount"],
42);
EXPECT_EQ(
json["Oem"]["Google"]["TransceiverTelemetry"]["FECUncorrectableCount"],
7);
EXPECT_EQ(json["Oem"]["Google"]["TransceiverTelemetry"]["PerLaneFECCounters"],
(std::vector<uint64_t>{10, 20, 30, 40}));
EXPECT_DOUBLE_EQ(json["Oem"]["Google"]["TransceiverTelemetry"]["BitErrorRate"]
.get<double>(),
1e-12);
EXPECT_EQ(json["LinkDownCount"], 2);
EXPECT_EQ(json["Oem"]["Google"]["PCIeErrors"]["ceCount"], 9);
EXPECT_EQ(json["Oem"]["Google"]["PCIeErrors"]["ueCount"], 0);
}
TEST_F(NetworkAdapterTest, GetNetworkPortDBusParallelMergedPldmPriority) {
auto* mockStore =
dynamic_cast<managedStore::MockSerializedManagedObjectStore*>(
managedStore::GetManagedObjectStore());
ASSERT_NE(mockStore, nullptr);
// 1. Mock Mapper GetSubTree returning both PLDM and NSM endpoints
managedStore::KeyType portSubTreeKey(
ManagedType::kManagedSubtree, "/xyz/openbmc_project/inventory", 0,
{"xyz.openbmc_project.Inventory.Item.Port"});
dbus::utility::MapperGetSubTreeResponse subtree = {
{"/xyz/openbmc_project/inventory/system/chassis/chassis0/adapter0/Port_1",
{{"xyz.openbmc_project.PLDM",
{"xyz.openbmc_project.Inventory.Item.Port"}}}},
{"/xyz/openbmc_project/inventory/system/chassis/chassis0/NetworkAdapters/"
"adapter0/Ports/Port_1",
{{"xyz.openbmc_project.NSM",
{"xyz.openbmc_project.Inventory.Item.Port"}}}}};
EXPECT_TRUE(
mockStore
->upsertMockObjectIntoManagedStore(
portSubTreeKey,
managedStore::MockManagedStoreTest::CreateValueType(subtree))
.ok());
// 2. Mock PLDM port properties (authoritative for link telemetry)
managedStore::KeyType pldmPropKey(
ManagedType::kManagedPropertyMap, "xyz.openbmc_project.PLDM",
sdbusplus::message::object_path(
"/xyz/openbmc_project/inventory/system/chassis/chassis0/adapter0/"
"Port_1"),
"xyz.openbmc_project.Inventory.Item.Port", "");
dbus::utility::DBusPropertiesMap pldmProps;
pldmProps.emplace_back(
"LinkState", dbus::utility::DbusVariantType(std::string("Enabled")));
pldmProps.emplace_back("LinkStatus",
dbus::utility::DbusVariantType(std::string("LinkUp")));
pldmProps.emplace_back("CurrentSpeedGbps",
dbus::utility::DbusVariantType(double{200.0}));
pldmProps.emplace_back("PortNumber",
dbus::utility::DbusVariantType(uint32_t{0}));
EXPECT_TRUE(
mockStore
->upsertMockObjectIntoManagedStore(
pldmPropKey,
managedStore::MockManagedStoreTest::CreateValueType(pldmProps))
.ok());
// 3. Mock NSM port properties (empty/unpopulated link telemetry, valid
// PortNumber)
managedStore::KeyType nsmPropKey(
ManagedType::kManagedPropertyMap, "xyz.openbmc_project.NSM",
sdbusplus::message::object_path("/xyz/openbmc_project/inventory/system/"
"chassis/chassis0/NetworkAdapters/"
"adapter0/Ports/Port_1"),
"xyz.openbmc_project.Inventory.Item.Port", "");
dbus::utility::DBusPropertiesMap nsmProps;
nsmProps.emplace_back("LinkState",
dbus::utility::DbusVariantType(std::string("")));
nsmProps.emplace_back("LinkStatus",
dbus::utility::DbusVariantType(std::string("")));
nsmProps.emplace_back("CurrentSpeedGbps",
dbus::utility::DbusVariantType(double{0.0}));
nsmProps.emplace_back("PortNumber",
dbus::utility::DbusVariantType(uint32_t{1}));
EXPECT_TRUE(
mockStore
->upsertMockObjectIntoManagedStore(
nsmPropKey,
managedStore::MockManagedStoreTest::CreateValueType(nsmProps))
.ok());
// 4. Mock Port LocationCode decorator (from PortLocationCodeMap)
managedStore::KeyType portLocCodeKey(
ManagedType::kManagedProperty, "xyz.openbmc_project.NSM",
sdbusplus::message::object_path("/xyz/openbmc_project/inventory/system/"
"chassis/chassis0/NetworkAdapters/"
"adapter0/Ports/Port_1"),
"xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode");
EXPECT_TRUE(
mockStore
->upsertMockObjectIntoManagedStore(
portLocCodeKey,
managedStore::MockManagedStoreTest::CreateValueType(
dbus::utility::DbusVariantType(std::string("port0_dev"))))
.ok());
// 5. Mock chassis paths
managedStore::KeyType chassisPathsKey(
ManagedType::kManagedSubtreePaths, "/xyz/openbmc_project/inventory", 0,
{"xyz.openbmc_project.Inventory.Item.Board",
"xyz.openbmc_project.Inventory.Item.Chassis"});
std::vector<std::string> chassisPaths = {
"/xyz/openbmc_project/inventory/system/chassis/chassis0"};
EXPECT_TRUE(
mockStore
->upsertMockObjectIntoManagedStore(
chassisPathsKey,
managedStore::MockManagedStoreTest::CreateValueType(chassisPaths))
.ok());
// 6. Mock chassis object interfaces
managedStore::KeyType chassisObjKey(
ManagedType::kManagedMapperObject,
"/xyz/openbmc_project/inventory/system/chassis/chassis0",
std::vector<std::string>{
"xyz.openbmc_project.Inventory.Decorator.LocationCode",
"xyz.openbmc_project.Inventory.Decorator.Location"});
dbus::utility::MapperGetObject chassisObj = {
{"xyz.openbmc_project.NSM",
{"xyz.openbmc_project.Inventory.Decorator.LocationCode",
"xyz.openbmc_project.Inventory.Decorator.Location"}}};
EXPECT_TRUE(
mockStore
->upsertMockObjectIntoManagedStore(
chassisObjKey,
managedStore::MockManagedStoreTest::CreateValueType(chassisObj))
.ok());
// 7. Mock chassis LocationCode and LocationType
managedStore::KeyType chassisLocCodeKey(
ManagedType::kManagedProperty, "xyz.openbmc_project.NSM",
sdbusplus::message::object_path(
"/xyz/openbmc_project/inventory/system/chassis/chassis0"),
"xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode");
EXPECT_TRUE(
mockStore
->upsertMockObjectIntoManagedStore(
chassisLocCodeKey,
managedStore::MockManagedStoreTest::CreateValueType(
dbus::utility::DbusVariantType(std::string("chassis0_loc"))))
.ok());
managedStore::KeyType chassisLocTypeKey(
ManagedType::kManagedProperty, "xyz.openbmc_project.NSM",
sdbusplus::message::object_path(
"/xyz/openbmc_project/inventory/system/chassis/chassis0"),
"xyz.openbmc_project.Inventory.Decorator.Location", "LocationType");
EXPECT_TRUE(mockStore
->upsertMockObjectIntoManagedStore(
chassisLocTypeKey,
managedStore::MockManagedStoreTest::CreateValueType(
dbus::utility::DbusVariantType(std::string(
"xyz.openbmc_project.Inventory.Decorator."
"Location.LocationTypes.Embedded"))))
.ok());
// 8. Mock chassis0 contained_by -> carrier_board
managedStore::KeyType chassisContainedByKey(
ManagedType::kManagedAssociatedSubtree,
"/xyz/openbmc_project/inventory/system/chassis/chassis0/contained_by",
"/xyz/openbmc_project/inventory", 0,
{"xyz.openbmc_project.Inventory.Item.Board",
"xyz.openbmc_project.Inventory.Item.Chassis"});
dbus::utility::MapperGetSubTreeResponse chassisContainedBy = {
{"/xyz/openbmc_project/inventory/system/board/carrier_board",
{{"xyz.openbmc_project.EntityManager",
{"xyz.openbmc_project.Inventory.Item.Board"}}}}};
EXPECT_TRUE(mockStore
->upsertMockObjectIntoManagedStore(
chassisContainedByKey,
managedStore::MockManagedStoreTest::CreateValueType(
chassisContainedBy))
.ok());
// 9. Mock carrier_board LocationCode
managedStore::KeyType carrierLocCodeKey(
ManagedType::kManagedProperty, "xyz.openbmc_project.EntityManager",
sdbusplus::message::object_path(
"/xyz/openbmc_project/inventory/system/board/carrier_board"),
"xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode");
EXPECT_TRUE(
mockStore
->upsertMockObjectIntoManagedStore(
carrierLocCodeKey,
managedStore::MockManagedStoreTest::CreateValueType(
dbus::utility::DbusVariantType(std::string("CARRIER"))))
.ok());
// 10. Mock carrier_board contained_by -> system_board
managedStore::KeyType carrierContainedByKey(
ManagedType::kManagedAssociatedSubtree,
"/xyz/openbmc_project/inventory/system/board/carrier_board/contained_by",
"/xyz/openbmc_project/inventory", 0,
{"xyz.openbmc_project.Inventory.Item.Board",
"xyz.openbmc_project.Inventory.Item.Chassis"});
dbus::utility::MapperGetSubTreeResponse carrierContainedBy = {
{"/xyz/openbmc_project/inventory/system/board/system_board",
{{"xyz.openbmc_project.EntityManager",
{"xyz.openbmc_project.Inventory.Item.Board"}}}}};
EXPECT_TRUE(mockStore
->upsertMockObjectIntoManagedStore(
carrierContainedByKey,
managedStore::MockManagedStoreTest::CreateValueType(
carrierContainedBy))
.ok());
// 11. Mock system_board LocationCode
managedStore::KeyType systemBoardLocCodeKey(
ManagedType::kManagedProperty, "xyz.openbmc_project.EntityManager",
sdbusplus::message::object_path(
"/xyz/openbmc_project/inventory/system/board/system_board"),
"xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode");
EXPECT_TRUE(
mockStore
->upsertMockObjectIntoManagedStore(
systemBoardLocCodeKey,
managedStore::MockManagedStoreTest::CreateValueType(
dbus::utility::DbusVariantType(std::string("SYSTEM_PLANE"))))
.ok());
// 12. Mock system_board contained_by -> empty
managedStore::KeyType systemBoardContainedByKey(
ManagedType::kManagedAssociatedSubtree,
"/xyz/openbmc_project/inventory/system/board/system_board/contained_by",
"/xyz/openbmc_project/inventory", 0,
{"xyz.openbmc_project.Inventory.Item.Board",
"xyz.openbmc_project.Inventory.Item.Chassis"});
dbus::utility::MapperGetSubTreeResponse systemBoardContainedBy = {};
EXPECT_TRUE(mockStore
->upsertMockObjectIntoManagedStore(
systemBoardContainedByKey,
managedStore::MockManagedStoreTest::CreateValueType(
systemBoardContainedBy))
.ok());
// 13. Mock system_board attached_cables -> empty
managedStore::KeyType attachedCablesKey(
ManagedType::kManagedProperty, "xyz.openbmc_project.ObjectMapper",
sdbusplus::message::object_path(
"/xyz/openbmc_project/inventory/system/board/system_board/"
"attached_cables"),
"xyz.openbmc_project.Association", "endpoints");
std::vector<std::string> emptyCables;
EXPECT_TRUE(mockStore
->upsertMockObjectIntoManagedStore(
attachedCablesKey,
managedStore::MockManagedStoreTest::CreateValueType(
dbus::utility::DbusVariantType(emptyCables)))
.ok());
handleNetworkPortGetDBus(share_async_resp_, "chassis0", "adapter0", "Port_1");
RunIoUntilDone();
nlohmann::json& json = share_async_resp_->res.jsonValue;
EXPECT_EQ(
json["@odata.id"],
"/redfish/v1/Chassis/chassis0/NetworkAdapters/adapter0/Ports/Port_1");
EXPECT_EQ(json["Id"], "Port_1");
EXPECT_EQ(json["Name"], "Port_1");
EXPECT_EQ(json["Status"]["State"], "Enabled");
EXPECT_EQ(json["Status"]["Health"], "OK");
EXPECT_EQ(json["Location"]["PartLocation"]["ServiceLabel"], "port0_dev");
EXPECT_EQ(json["Location"]["PartLocation"]["LocationType"], "Embedded");
EXPECT_EQ(json["Location"]["PartLocationContext"], "SYSTEM_PLANE/CARRIER");
EXPECT_EQ(json["Location"]["Oem"]["Google"]["Devpath"],
"/phys/SYSTEM_PLANE/CARRIER:device:port0_dev");
EXPECT_EQ(json["LinkState"], "Enabled");
EXPECT_EQ(json["LinkStatus"], "LinkUp");
EXPECT_DOUBLE_EQ(json["CurrentSpeedGbps"].get<double>(), 200.0);
EXPECT_EQ(json["Metrics"]["@odata.id"],
"/redfish/v1/Chassis/chassis0/NetworkAdapters/adapter0/Ports/"
"Port_1/Metrics");
}
TEST_F(NetworkAdapterTest, GetNetworkPortDBusPldmOnly) {
auto* mockStore =
dynamic_cast<managedStore::MockSerializedManagedObjectStore*>(
managedStore::GetManagedObjectStore());
ASSERT_NE(mockStore, nullptr);
managedStore::KeyType portSubTreeKey(
ManagedType::kManagedSubtree, "/xyz/openbmc_project/inventory", 0,
{"xyz.openbmc_project.Inventory.Item.Port"});
dbus::utility::MapperGetSubTreeResponse subtree = {
{"/xyz/openbmc_project/inventory/system/chassis/chassis0/adapter0/Port_1",
{{"xyz.openbmc_project.PLDM",
{"xyz.openbmc_project.Inventory.Item.Port"}}}}};
EXPECT_TRUE(
mockStore
->upsertMockObjectIntoManagedStore(
portSubTreeKey,
managedStore::MockManagedStoreTest::CreateValueType(subtree))
.ok());
managedStore::KeyType pldmPropKey(
ManagedType::kManagedPropertyMap, "xyz.openbmc_project.PLDM",
sdbusplus::message::object_path(
"/xyz/openbmc_project/inventory/system/chassis/chassis0/adapter0/"
"Port_1"),
"xyz.openbmc_project.Inventory.Item.Port", "");
dbus::utility::DBusPropertiesMap pldmProps;
pldmProps.emplace_back(
"LinkState", dbus::utility::DbusVariantType(std::string("Enabled")));
pldmProps.emplace_back("LinkStatus",
dbus::utility::DbusVariantType(std::string("LinkUp")));
pldmProps.emplace_back("CurrentSpeedGbps",
dbus::utility::DbusVariantType(double{100.0}));
EXPECT_TRUE(
mockStore
->upsertMockObjectIntoManagedStore(
pldmPropKey,
managedStore::MockManagedStoreTest::CreateValueType(pldmProps))
.ok());
handleNetworkPortGetDBus(share_async_resp_, "chassis0", "adapter0", "Port_1");
RunIoUntilDone();
nlohmann::json& json = share_async_resp_->res.jsonValue;
EXPECT_EQ(json["Status"]["State"], "Enabled");
EXPECT_EQ(json["Status"]["Health"], "OK");
EXPECT_EQ(json["LinkState"], "Enabled");
EXPECT_EQ(json["LinkStatus"], "LinkUp");
EXPECT_DOUBLE_EQ(json["CurrentSpeedGbps"].get<double>(), 100.0);
}
TEST_F(NetworkAdapterTest, GetNetworkPortDBusPldmPriorityOverNonEmptyNsm) {
auto* mockStore =
dynamic_cast<managedStore::MockSerializedManagedObjectStore*>(
managedStore::GetManagedObjectStore());
ASSERT_NE(mockStore, nullptr);
// 1. Mock Mapper GetSubTree returning both PLDM and NSM endpoints
managedStore::KeyType portSubTreeKey(
ManagedType::kManagedSubtree, "/xyz/openbmc_project/inventory", 0,
{"xyz.openbmc_project.Inventory.Item.Port"});
dbus::utility::MapperGetSubTreeResponse subtree = {
{"/xyz/openbmc_project/inventory/system/chassis/chassis0/adapter0/Port_1",
{{"xyz.openbmc_project.PLDM",
{"xyz.openbmc_project.Inventory.Item.Port"}}}},
{"/xyz/openbmc_project/inventory/system/chassis/chassis0/NetworkAdapters/"
"adapter0/Ports/Port_1",
{{"xyz.openbmc_project.NSM",
{"xyz.openbmc_project.Inventory.Item.Port"}}}}};
EXPECT_TRUE(
mockStore
->upsertMockObjectIntoManagedStore(
portSubTreeKey,
managedStore::MockManagedStoreTest::CreateValueType(subtree))
.ok());
// 2. Mock PLDM port properties (authoritative for base link telemetry)
managedStore::KeyType pldmPropKey(
ManagedType::kManagedPropertyMap, "xyz.openbmc_project.PLDM",
sdbusplus::message::object_path(
"/xyz/openbmc_project/inventory/system/chassis/chassis0/adapter0/"
"Port_1"),
"xyz.openbmc_project.Inventory.Item.Port", "");
dbus::utility::DBusPropertiesMap pldmProps;
pldmProps.emplace_back(
"LinkState", dbus::utility::DbusVariantType(std::string("Enabled")));
pldmProps.emplace_back("LinkStatus",
dbus::utility::DbusVariantType(std::string("LinkUp")));
pldmProps.emplace_back("CurrentSpeedGbps",
dbus::utility::DbusVariantType(double{100.0}));
EXPECT_TRUE(
mockStore
->upsertMockObjectIntoManagedStore(
pldmPropKey,
managedStore::MockManagedStoreTest::CreateValueType(pldmProps))
.ok());
// 3. Mock NSM port properties with conflicting non-empty link telemetry
managedStore::KeyType nsmPropKey(
ManagedType::kManagedPropertyMap, "xyz.openbmc_project.NSM",
sdbusplus::message::object_path("/xyz/openbmc_project/inventory/system/"
"chassis/chassis0/NetworkAdapters/"
"adapter0/Ports/Port_1"),
"xyz.openbmc_project.Inventory.Item.Port", "");
dbus::utility::DBusPropertiesMap nsmProps;
nsmProps.emplace_back(
"LinkState", dbus::utility::DbusVariantType(std::string("Disabled")));
nsmProps.emplace_back(
"LinkStatus", dbus::utility::DbusVariantType(std::string("LinkDown")));
nsmProps.emplace_back("CurrentSpeedGbps",
dbus::utility::DbusVariantType(double{400.0}));
EXPECT_TRUE(
mockStore
->upsertMockObjectIntoManagedStore(
nsmPropKey,
managedStore::MockManagedStoreTest::CreateValueType(nsmProps))
.ok());
handleNetworkPortGetDBus(share_async_resp_, "chassis0", "adapter0", "Port_1");
RunIoUntilDone();
EXPECT_EQ(share_async_resp_->res.result(), boost::beast::http::status::ok);
nlohmann::json& json = share_async_resp_->res.jsonValue;
EXPECT_EQ(json["Status"]["State"], "Enabled");
EXPECT_EQ(json["Status"]["Health"], "OK");
EXPECT_EQ(json["LinkState"], "Enabled");
EXPECT_EQ(json["LinkStatus"], "LinkUp");
EXPECT_DOUBLE_EQ(json["CurrentSpeedGbps"].get<double>(), 100.0);
}
TEST_F(NetworkAdapterTest,
GetNetworkPortDBusMissingPropertiesReturnsInternalError) {
auto* mockStore =
dynamic_cast<managedStore::MockSerializedManagedObjectStore*>(
managedStore::GetManagedObjectStore());
ASSERT_NE(mockStore, nullptr);
managedStore::KeyType portSubTreeKey(
ManagedType::kManagedSubtree, "/xyz/openbmc_project/inventory", 0,
{"xyz.openbmc_project.Inventory.Item.Port"});
dbus::utility::MapperGetSubTreeResponse subtree = {
{"/xyz/openbmc_project/inventory/system/chassis/chassis0/NetworkAdapters/"
"adapter0/Ports/Port_1",
{{"xyz.openbmc_project.NSM",
{"xyz.openbmc_project.Inventory.Item.Port"}}}}};
EXPECT_TRUE(
mockStore
->upsertMockObjectIntoManagedStore(
portSubTreeKey,
managedStore::MockManagedStoreTest::CreateValueType(subtree))
.ok());
managedStore::KeyType nsmPropKey(
ManagedType::kManagedPropertyMap, "xyz.openbmc_project.NSM",
sdbusplus::message::object_path("/xyz/openbmc_project/inventory/system/"
"chassis/chassis0/NetworkAdapters/"
"adapter0/Ports/Port_1"),
"xyz.openbmc_project.Inventory.Item.Port", "");
dbus::utility::DBusPropertiesMap nsmProps;
nsmProps.emplace_back("LinkState",
dbus::utility::DbusVariantType(std::string("")));
nsmProps.emplace_back("LinkStatus",
dbus::utility::DbusVariantType(std::string("")));
EXPECT_TRUE(
mockStore
->upsertMockObjectIntoManagedStore(
nsmPropKey,
managedStore::MockManagedStoreTest::CreateValueType(nsmProps))
.ok());
handleNetworkPortGetDBus(share_async_resp_, "chassis0", "adapter0", "Port_1");
RunIoUntilDone();
EXPECT_EQ(share_async_resp_->res.result(),
boost::beast::http::status::internal_server_error);
}
TEST_F(NetworkAdapterTest, GetNetworkPortDBusPldmMissingFallsBackToNsm) {
auto* mockStore =
dynamic_cast<managedStore::MockSerializedManagedObjectStore*>(
managedStore::GetManagedObjectStore());
ASSERT_NE(mockStore, nullptr);
managedStore::KeyType portSubTreeKey(
ManagedType::kManagedSubtree, "/xyz/openbmc_project/inventory", 0,
{"xyz.openbmc_project.Inventory.Item.Port"});
dbus::utility::MapperGetSubTreeResponse subtree = {
{"/xyz/openbmc_project/inventory/system/chassis/chassis0/adapter0/Port_1",
{{"xyz.openbmc_project.PLDM",
{"xyz.openbmc_project.Inventory.Item.Port"}}}},
{"/xyz/openbmc_project/inventory/system/chassis/chassis0/NetworkAdapters/"
"adapter0/Ports/Port_1",
{{"xyz.openbmc_project.NSM",
{"xyz.openbmc_project.Inventory.Item.Port"}}}}};
EXPECT_TRUE(
mockStore
->upsertMockObjectIntoManagedStore(
portSubTreeKey,
managedStore::MockManagedStoreTest::CreateValueType(subtree))
.ok());
// PLDM has empty properties (fails to provide telemetry)
managedStore::KeyType pldmPropKey(
ManagedType::kManagedPropertyMap, "xyz.openbmc_project.PLDM",
sdbusplus::message::object_path(
"/xyz/openbmc_project/inventory/system/chassis/chassis0/adapter0/"
"Port_1"),
"xyz.openbmc_project.Inventory.Item.Port", "");
dbus::utility::DBusPropertiesMap pldmProps;
pldmProps.emplace_back("LinkState",
dbus::utility::DbusVariantType(std::string("")));
pldmProps.emplace_back("LinkStatus",
dbus::utility::DbusVariantType(std::string("")));
pldmProps.emplace_back("CurrentSpeedGbps",
dbus::utility::DbusVariantType(double{0.0}));
EXPECT_TRUE(
mockStore
->upsertMockObjectIntoManagedStore(
pldmPropKey,
managedStore::MockManagedStoreTest::CreateValueType(pldmProps))
.ok());
// NSM has valid properties (provides fallback telemetry)
managedStore::KeyType nsmPropKey(
ManagedType::kManagedPropertyMap, "xyz.openbmc_project.NSM",
sdbusplus::message::object_path("/xyz/openbmc_project/inventory/system/"
"chassis/chassis0/NetworkAdapters/"
"adapter0/Ports/Port_1"),
"xyz.openbmc_project.Inventory.Item.Port", "");
dbus::utility::DBusPropertiesMap nsmProps;
nsmProps.emplace_back("LinkState",
dbus::utility::DbusVariantType(std::string("Enabled")));
nsmProps.emplace_back("LinkStatus",
dbus::utility::DbusVariantType(std::string("LinkUp")));
nsmProps.emplace_back("CurrentSpeedGbps",
dbus::utility::DbusVariantType(double{200.0}));
EXPECT_TRUE(
mockStore
->upsertMockObjectIntoManagedStore(
nsmPropKey,
managedStore::MockManagedStoreTest::CreateValueType(nsmProps))
.ok());
handleNetworkPortGetDBus(share_async_resp_, "chassis0", "adapter0", "Port_1");
RunIoUntilDone();
EXPECT_EQ(share_async_resp_->res.result(), boost::beast::http::status::ok);
nlohmann::json& json = share_async_resp_->res.jsonValue;
EXPECT_EQ(json["LinkState"], "Enabled");
EXPECT_EQ(json["LinkStatus"], "LinkUp");
EXPECT_DOUBLE_EQ(json["CurrentSpeedGbps"].get<double>(), 200.0);
}
TEST_F(NetworkAdapterTest, GetNetworkPortDBusBothMissingReturnsInternalError) {
auto* mockStore =
dynamic_cast<managedStore::MockSerializedManagedObjectStore*>(
managedStore::GetManagedObjectStore());
ASSERT_NE(mockStore, nullptr);
managedStore::KeyType portSubTreeKey(
ManagedType::kManagedSubtree, "/xyz/openbmc_project/inventory", 0,
{"xyz.openbmc_project.Inventory.Item.Port"});
dbus::utility::MapperGetSubTreeResponse subtree = {
{"/xyz/openbmc_project/inventory/system/chassis/chassis0/adapter0/Port_1",
{{"xyz.openbmc_project.PLDM",
{"xyz.openbmc_project.Inventory.Item.Port"}}}},
{"/xyz/openbmc_project/inventory/system/chassis/chassis0/NetworkAdapters/"
"adapter0/Ports/Port_1",
{{"xyz.openbmc_project.NSM",
{"xyz.openbmc_project.Inventory.Item.Port"}}}}};
EXPECT_TRUE(
mockStore
->upsertMockObjectIntoManagedStore(
portSubTreeKey,
managedStore::MockManagedStoreTest::CreateValueType(subtree))
.ok());
// Both PLDM and NSM have empty properties
managedStore::KeyType pldmPropKey(
ManagedType::kManagedPropertyMap, "xyz.openbmc_project.PLDM",
sdbusplus::message::object_path(
"/xyz/openbmc_project/inventory/system/chassis/chassis0/adapter0/"
"Port_1"),
"xyz.openbmc_project.Inventory.Item.Port", "");
dbus::utility::DBusPropertiesMap pldmProps;
pldmProps.emplace_back("LinkState",
dbus::utility::DbusVariantType(std::string("")));
pldmProps.emplace_back("LinkStatus",
dbus::utility::DbusVariantType(std::string("")));
pldmProps.emplace_back("CurrentSpeedGbps",
dbus::utility::DbusVariantType(double{0.0}));
EXPECT_TRUE(
mockStore
->upsertMockObjectIntoManagedStore(
pldmPropKey,
managedStore::MockManagedStoreTest::CreateValueType(pldmProps))
.ok());
managedStore::KeyType nsmPropKey(
ManagedType::kManagedPropertyMap, "xyz.openbmc_project.NSM",
sdbusplus::message::object_path("/xyz/openbmc_project/inventory/system/"
"chassis/chassis0/NetworkAdapters/"
"adapter0/Ports/Port_1"),
"xyz.openbmc_project.Inventory.Item.Port", "");
dbus::utility::DBusPropertiesMap nsmProps;
nsmProps.emplace_back("LinkState",
dbus::utility::DbusVariantType(std::string("")));
nsmProps.emplace_back("LinkStatus",
dbus::utility::DbusVariantType(std::string("")));
nsmProps.emplace_back("CurrentSpeedGbps",
dbus::utility::DbusVariantType(double{0.0}));
EXPECT_TRUE(
mockStore
->upsertMockObjectIntoManagedStore(
nsmPropKey,
managedStore::MockManagedStoreTest::CreateValueType(nsmProps))
.ok());
handleNetworkPortGetDBus(share_async_resp_, "chassis0", "adapter0", "Port_1");
RunIoUntilDone();
EXPECT_EQ(share_async_resp_->res.result(),
boost::beast::http::status::internal_server_error);
}
TEST_F(NetworkAdapterTest,
NetworkAdapterCollectionDBusDeduplicatesMultipleEndpoints) {
auto* mockStore =
dynamic_cast<managedStore::MockSerializedManagedObjectStore*>(
managedStore::GetManagedObjectStore());
ASSERT_NE(mockStore, nullptr);
managedStore::KeyType chassisSubTreeKey(
ManagedType::kManagedSubtree, "/xyz/openbmc_project/inventory", 0,
{"xyz.openbmc_project.Inventory.Item.Board",
"xyz.openbmc_project.Inventory.Item.Chassis"});
dbus::utility::MapperGetSubTreeResponse chassisSubtree = {
{"/xyz/openbmc_project/inventory/system/chassis/chassis0",
{{"xyz.openbmc_project.PLDM",
{"xyz.openbmc_project.Inventory.Item.Board"}}}}};
EXPECT_TRUE(mockStore
->upsertMockObjectIntoManagedStore(
chassisSubTreeKey,
managedStore::MockManagedStoreTest::CreateValueType(
chassisSubtree))
.ok());
managedStore::KeyType assocKey(
managedStore::ManagedType::kManagedProperty,
"xyz.openbmc_project.ObjectMapper",
sdbusplus::message::object_path("/xyz/openbmc_project/inventory/system/"
"chassis/chassis0/network_adapter"),
"xyz.openbmc_project.Association", "endpoints");
dbus::utility::MapperEndPoints endpoints = {
"/xyz/openbmc_project/inventory/system/chassis/chassis0/NetworkAdapters/"
"adapter0",
"/xyz/openbmc_project/inventory/system/chassis/chassis0/adapter0"};
EXPECT_TRUE(
mockStore
->upsertMockObjectIntoManagedStore(
assocKey, managedStore::MockManagedStoreTest::CreateValueType(
dbus::utility::DbusVariantType(endpoints)))
.ok());
handleChassisNetworkAdapterCollectionGetDBus(share_async_resp_, "chassis0");
RunIoUntilDone();
EXPECT_EQ(share_async_resp_->res.result(), boost::beast::http::status::ok);
nlohmann::json& json = share_async_resp_->res.jsonValue;
EXPECT_EQ(json["@odata.type"],
"#NetworkAdapterCollection.NetworkAdapterCollection");
EXPECT_EQ(json["Members@odata.count"], 1);
EXPECT_EQ(json["Members"].size(), 1);
EXPECT_EQ(json["Members"][0]["@odata.id"],
"/redfish/v1/Chassis/chassis0/NetworkAdapters/adapter0");
}
TEST_F(NetworkAdapterTest,
NetworkPortCollectionDBusDeduplicatesMultipleEndpoints) {
auto* mockStore =
dynamic_cast<managedStore::MockSerializedManagedObjectStore*>(
managedStore::GetManagedObjectStore());
ASSERT_NE(mockStore, nullptr);
managedStore::KeyType adapterSubTreeKey(
ManagedType::kManagedSubtree, "/xyz/openbmc_project/inventory", 0,
{"xyz.openbmc_project.Inventory.Item.NetworkAdapter"});
dbus::utility::MapperGetSubTreeResponse adapterSubtree = {
{"/xyz/openbmc_project/inventory/system/chassis/chassis0/adapter0",
{{"xyz.openbmc_project.PLDM",
{"xyz.openbmc_project.Inventory.Item.NetworkAdapter"}}}},
{"/xyz/openbmc_project/inventory/system/chassis/chassis0/NetworkAdapters/"
"adapter0",
{{"xyz.openbmc_project.NSM",
{"xyz.openbmc_project.Inventory.Item.NetworkAdapter"}}}}};
EXPECT_TRUE(mockStore
->upsertMockObjectIntoManagedStore(
adapterSubTreeKey,
managedStore::MockManagedStoreTest::CreateValueType(
adapterSubtree))
.ok());
managedStore::KeyType pldmAssocKey(
managedStore::ManagedType::kManagedProperty,
"xyz.openbmc_project.ObjectMapper",
sdbusplus::message::object_path(
"/xyz/openbmc_project/inventory/system/chassis/chassis0/adapter0/"
"all_ports"),
"xyz.openbmc_project.Association", "endpoints");
dbus::utility::MapperEndPoints pldmEndpoints = {
"/xyz/openbmc_project/inventory/system/chassis/chassis0/adapter0/Port_1",
"/xyz/openbmc_project/inventory/system/chassis/chassis0/adapter0/Port_2"};
EXPECT_TRUE(
mockStore
->upsertMockObjectIntoManagedStore(
pldmAssocKey, managedStore::MockManagedStoreTest::CreateValueType(
dbus::utility::DbusVariantType(pldmEndpoints)))
.ok());
managedStore::KeyType nsmAssocKey(
managedStore::ManagedType::kManagedProperty,
"xyz.openbmc_project.ObjectMapper",
sdbusplus::message::object_path("/xyz/openbmc_project/inventory/system/"
"chassis/chassis0/NetworkAdapters/"
"adapter0/all_ports"),
"xyz.openbmc_project.Association", "endpoints");
dbus::utility::MapperEndPoints nsmEndpoints = {
"/xyz/openbmc_project/inventory/system/chassis/chassis0/NetworkAdapters/"
"adapter0/Ports/Port_1",
"/xyz/openbmc_project/inventory/system/chassis/chassis0/NetworkAdapters/"
"adapter0/Ports/Port_3"};
EXPECT_TRUE(
mockStore
->upsertMockObjectIntoManagedStore(
nsmAssocKey, managedStore::MockManagedStoreTest::CreateValueType(
dbus::utility::DbusVariantType(nsmEndpoints)))
.ok());
handleNetworkPortCollectionGetDBus(share_async_resp_, "chassis0", "adapter0");
RunIoUntilDone();
EXPECT_EQ(share_async_resp_->res.result(), boost::beast::http::status::ok);
nlohmann::json& json = share_async_resp_->res.jsonValue;
EXPECT_EQ(json["@odata.type"], "#PortCollection.PortCollection");
EXPECT_EQ(json["Members@odata.count"], 3);
EXPECT_EQ(json["Members"].size(), 3);
EXPECT_EQ(
json["Members"][0]["@odata.id"],
"/redfish/v1/Chassis/chassis0/NetworkAdapters/adapter0/Ports/Port_1");
EXPECT_EQ(
json["Members"][1]["@odata.id"],
"/redfish/v1/Chassis/chassis0/NetworkAdapters/adapter0/Ports/Port_2");
EXPECT_EQ(
json["Members"][2]["@odata.id"],
"/redfish/v1/Chassis/chassis0/NetworkAdapters/adapter0/Ports/Port_3");
}
TEST(FindPortProviderEndpointsTest, IgnoresEmptyConnectionAndReturnsEndpoints) {
dbus::utility::MapperGetSubTreeResponse subtree = {
{"/xyz/openbmc_project/inventory/system/chassis/chassis0/adapter0/Port_1",
{}},
{"/xyz/openbmc_project/inventory/system/chassis/chassis0/adapter0/Port_1",
{{"xyz.openbmc_project.PLDM",
{"xyz.openbmc_project.Inventory.Item.Port"}}}},
{"/xyz/openbmc_project/inventory/system/chassis/chassis0/NetworkAdapters/"
"adapter0/Ports/Port_1",
{{"xyz.openbmc_project.NSM",
{"xyz.openbmc_project.Inventory.Item.Port"}}}}};
PortProviderEndpoints ep =
findPortProviderEndpoints(subtree, "chassis0", "adapter0", "Port_1");
EXPECT_EQ(
ep.pldm.first,
"/xyz/openbmc_project/inventory/system/chassis/chassis0/adapter0/Port_1");
EXPECT_EQ(ep.pldm.second, "xyz.openbmc_project.PLDM");
EXPECT_EQ(
ep.nsm.first,
"/xyz/openbmc_project/inventory/system/chassis/chassis0/NetworkAdapters/"
"adapter0/Ports/Port_1");
EXPECT_EQ(ep.nsm.second, "xyz.openbmc_project.NSM");
}
TEST_F(NetworkAdapterTest,
BuildNetworkPortDBusReturnsNotFoundWhenBothEndpointsEmpty) {
buildNetworkPortDBus(share_async_resp_, "chassis0", "adapter0", "Port_1",
/*pldmEndpoint=*/{"", ""}, /*nsmEndpoint=*/{"", ""});
EXPECT_EQ(share_async_resp_->res.result(),
boost::beast::http::status::not_found);
}
TEST_F(NetworkAdapterTest,
NetworkPortGetDBusReturnsNotFoundWhenNoMatchingEndpoints) {
auto* mockStore =
dynamic_cast<managedStore::MockSerializedManagedObjectStore*>(
managedStore::GetManagedObjectStore());
ASSERT_NE(mockStore, nullptr);
managedStore::KeyType portSubTreeKey(
ManagedType::kManagedSubtree, "/xyz/openbmc_project/inventory", 0,
{"xyz.openbmc_project.Inventory.Item.Port"});
dbus::utility::MapperGetSubTreeResponse subtree = {
{"/xyz/openbmc_project/inventory/system/chassis/chassis0/adapter0/"
"Port_99",
{{"xyz.openbmc_project.PLDM",
{"xyz.openbmc_project.Inventory.Item.Port"}}}}};
EXPECT_TRUE(
mockStore
->upsertMockObjectIntoManagedStore(
portSubTreeKey,
managedStore::MockManagedStoreTest::CreateValueType(subtree))
.ok());
handleNetworkPortGetDBus(share_async_resp_, "chassis0", "adapter0", "Port_1");
RunIoUntilDone();
EXPECT_EQ(share_async_resp_->res.result(),
boost::beast::http::status::not_found);
}
} // namespace
} // namespace redfish