gbmcweb: Expose Corrupted property in RawEeproms endpoint Google-Bug-Id:492137013,570840373 PiperOrigin-RevId: 1003372131 Change-Id: Idc33a9334908178670af4530a4c24b4d191b5bb0
diff --git a/redfish-core/lib/managers.hpp b/redfish-core/lib/managers.hpp index e182dcc..d35fee4 100644 --- a/redfish-core/lib/managers.hpp +++ b/redfish-core/lib/managers.hpp
@@ -2689,6 +2689,7 @@ uint32_t address = 0; bool hasBus = false; bool hasAddress = false; + std::optional<bool> corrupted; for (const auto& [propertyName, value] : propertiesList) { if (propertyName == "Bus") { @@ -2711,6 +2712,11 @@ address = static_cast<uint32_t>(*a64); hasAddress = true; } + } else if (propertyName == "Corrupted") { + if (const bool* corruptedValue = std::get_if<bool>(&value); + corruptedValue != nullptr) { + corrupted = *corruptedValue; + } } } @@ -2738,7 +2744,7 @@ asyncResp->strand_, absl::AnyInvocable<void(const boost::system::error_code&, const std::vector<uint8_t>&)>( - [asyncResp, rawId]( + [asyncResp, rawId, corrupted]( const boost::system::error_code& ec2, const std::vector<uint8_t>& rawData) { if (ec2) { @@ -2757,6 +2763,10 @@ messages::internalError(asyncResp->res); return; } + if (corrupted.has_value()) { + asyncResp->res.jsonValue["Corrupted"] = + *corrupted; + } asyncResp->res.jsonValue["Status"]["State"] = "Enabled"; asyncResp->res.jsonValue["RawData"] = rawData;
diff --git a/test/redfish-core/lib/manager_test.cpp b/test/redfish-core/lib/manager_test.cpp index c93dd77..5977dd8 100644 --- a/test/redfish-core/lib/manager_test.cpp +++ b/test/redfish-core/lib/manager_test.cpp
@@ -9,6 +9,8 @@ #include <gmock/gmock.h> #include <gtest/gtest.h> #include "absl/functional/any_invocable.h" +#include "absl/strings/str_cat.h" +#include "absl/strings/string_view.h" #include "http_request.hpp" #include "http_response.hpp" #include "async_resp.hpp" @@ -34,6 +36,10 @@ using ::managedStore::ManagedType; using ::managedStore::SimulateFailedAsyncPostDbusCallThreadSafeWithEmptyValueAction; using ::managedStore::ValueType; +using ::testing::_; +using ::testing::An; +using ::testing::Eq; +using ::testing::NotNull; constexpr char kClassType[] = "Temperature"; constexpr char kSensor[] = "sensor0"; @@ -735,6 +741,183 @@ EXPECT_EQ(share_async_resp_->res.result(), boost::beast::http::status::ok); } +void UpsertMockRawEepromProperties( + managedStore::MockSerializedManagedObjectStore& mock_store, + absl::string_view raw_id, uint32_t bus, uint32_t address, bool corrupted) { + const std::string object_path = + absl::StrCat("/xyz/openbmc_project/FruDevice/", raw_id); + KeyType mapper_key( + ManagedType::kManagedMapperObject, object_path, + std::vector<std::string>{"xyz.openbmc_project.Inventory.Item.I2CDevice"}); + dbus::utility::MapperGetObject mapper_object = { + {"xyz.openbmc_project.FruDevice", + {"xyz.openbmc_project.Inventory.Item.I2CDevice"}}}; + ASSERT_TRUE( + mock_store + .upsertMockObjectIntoManagedStore( + mapper_key, managedStore::MockManagedStoreTest::CreateValueType( + mapper_object)) + .ok()); + + KeyType properties_key(ManagedType::kManagedPropertyMap, + "xyz.openbmc_project.FruDevice", object_path, + "xyz.openbmc_project.Inventory.Item.I2CDevice"); + DBusPropertiesMap properties = { + {"Bus", DbusVariantType(bus)}, + {"Address", DbusVariantType(address)}, + {"Corrupted", DbusVariantType(corrupted)}, + }; + ASSERT_TRUE( + mock_store + .upsertMockObjectIntoManagedStore( + properties_key, + managedStore::MockManagedStoreTest::CreateValueType(properties)) + .ok()); +} + +// Tests that "Corrupted": true is included in the response when the EEPROM has +// Corrupted set to true on D-Bus. +TEST_F(SnapshotFixture, + HandleRawEepromMemberGetCorruptedTrueReturnsCorruptedField) { + auto* mock_store = + dynamic_cast<managedStore::MockSerializedManagedObjectStore*>( + managedStore::GetManagedObjectStore()); + ASSERT_THAT(mock_store, NotNull()); + UpsertMockRawEepromProperties(*mock_store, /*raw_id=*/"22_80", /*bus=*/22, + /*address=*/80, /*corrupted=*/true); + + EXPECT_CALL( + *mock_store, + PostDbusCallToIoContextThreadSafe( + _, + An<absl::AnyInvocable<void(const boost::system::error_code&, + const std::vector<uint8_t>&)>&&>(), + "xyz.openbmc_project.FruDevice", "/xyz/openbmc_project/FruDevice", + "xyz.openbmc_project.FruDeviceManager", "GetRawFru", Eq(uint16_t{22}), + Eq(uint8_t{80}))) + .WillOnce( + managedStore:: + SimulateSuccessfulAsyncPostDbusCallThreadSafeWithValueAction< + std::vector<uint8_t>>:: + SimulateSuccessfulAsyncPostDbusCallWithValue( + std::make_shared<std::vector<uint8_t>>( + std::vector<uint8_t>{1, 2, 3}))); + + handleRawEepromMemberGet(app_, CreateRequest(), share_async_resp_, "22_80"); + + RunIoUntilDone(); + + EXPECT_EQ(share_async_resp_->res.jsonValue, nlohmann::json::parse(R"json({ + "@odata.id": "/redfish/v1/Managers/bmc/Oem/Google/FruDevice/RawEeproms/22_80", + "@odata.type": "#GoogleFruDevice.v1_0_0.RawEeprom", + "Id": "22_80", + "Name": "Google Raw EEPROM", + "Bus": 22, + "Address": 80, + "Corrupted": true, + "Status": { + "State": "Enabled" + }, + "RawData": [1, 2, 3], + "HexdumpFormattedRawData": "0000: 01 02 03 | ... |\n" + })json")); + EXPECT_EQ(share_async_resp_->res.result(), boost::beast::http::status::ok); +} + +// Tests that "Corrupted": false is included in the response when the EEPROM has +// Corrupted set to false on D-Bus. +TEST_F(SnapshotFixture, + HandleRawEepromMemberGetCorruptedFalseReturnsCorruptedField) { + auto* mock_store = + dynamic_cast<managedStore::MockSerializedManagedObjectStore*>( + managedStore::GetManagedObjectStore()); + ASSERT_THAT(mock_store, NotNull()); + UpsertMockRawEepromProperties(*mock_store, /*raw_id=*/"22_80", /*bus=*/22, + /*address=*/80, /*corrupted=*/false); + + EXPECT_CALL( + *mock_store, + PostDbusCallToIoContextThreadSafe( + _, + An<absl::AnyInvocable<void(const boost::system::error_code&, + const std::vector<uint8_t>&)>&&>(), + "xyz.openbmc_project.FruDevice", "/xyz/openbmc_project/FruDevice", + "xyz.openbmc_project.FruDeviceManager", "GetRawFru", Eq(uint16_t{22}), + Eq(uint8_t{80}))) + .WillOnce( + managedStore:: + SimulateSuccessfulAsyncPostDbusCallThreadSafeWithValueAction< + std::vector<uint8_t>>:: + SimulateSuccessfulAsyncPostDbusCallWithValue( + std::make_shared<std::vector<uint8_t>>( + std::vector<uint8_t>{1, 2, 3}))); + + handleRawEepromMemberGet(app_, CreateRequest(), share_async_resp_, "22_80"); + + RunIoUntilDone(); + + EXPECT_EQ(share_async_resp_->res.jsonValue, nlohmann::json::parse(R"json({ + "@odata.id": "/redfish/v1/Managers/bmc/Oem/Google/FruDevice/RawEeproms/22_80", + "@odata.type": "#GoogleFruDevice.v1_0_0.RawEeprom", + "Id": "22_80", + "Name": "Google Raw EEPROM", + "Bus": 22, + "Address": 80, + "Corrupted": false, + "Status": { + "State": "Enabled" + }, + "RawData": [1, 2, 3], + "HexdumpFormattedRawData": "0000: 01 02 03 | ... |\n" + })json")); + EXPECT_EQ(share_async_resp_->res.result(), boost::beast::http::status::ok); +} + +// Tests that "Corrupted" is omitted when GetRawFru fails with invalid_argument +// (State: "Disabled") even if Corrupted is false on D-Bus. +TEST_F(SnapshotFixture, + HandleRawEepromMemberGetNotPopulatedOmitsCorruptedField) { + auto* mock_store = + dynamic_cast<managedStore::MockSerializedManagedObjectStore*>( + managedStore::GetManagedObjectStore()); + ASSERT_THAT(mock_store, NotNull()); + UpsertMockRawEepromProperties(*mock_store, /*raw_id=*/"22_80", /*bus=*/22, + /*address=*/80, /*corrupted=*/false); + + EXPECT_CALL( + *mock_store, + PostDbusCallToIoContextThreadSafe( + _, + An<absl::AnyInvocable<void(const boost::system::error_code&, + const std::vector<uint8_t>&)>&&>(), + "xyz.openbmc_project.FruDevice", "/xyz/openbmc_project/FruDevice", + "xyz.openbmc_project.FruDeviceManager", "GetRawFru", Eq(uint16_t{22}), + Eq(uint8_t{80}))) + .WillOnce( + managedStore:: + SimulateFailedAsyncPostDbusCallThreadSafeWithEmptyValueAction:: + SimulateFailedAsyncPostDbusCallWithEmptyValue( + boost::system::errc::make_error_code( + boost::system::errc::invalid_argument))); + + handleRawEepromMemberGet(app_, CreateRequest(), share_async_resp_, "22_80"); + + RunIoUntilDone(); + + EXPECT_EQ(share_async_resp_->res.jsonValue, nlohmann::json::parse(R"json({ + "@odata.id": "/redfish/v1/Managers/bmc/Oem/Google/FruDevice/RawEeproms/22_80", + "@odata.type": "#GoogleFruDevice.v1_0_0.RawEeprom", + "Id": "22_80", + "Name": "Google Raw EEPROM", + "Bus": 22, + "Address": 80, + "Status": { + "State": "Disabled" + } + })json")); + EXPECT_EQ(share_async_resp_->res.result(), boost::beast::http::status::ok); +} + TEST_F(SnapshotFixture, handleRawEepromMemberGetZeroLength) { std::string rawId = "Eeprom1"; KeyType key(ManagedType::kManagedPropertyMap, "xyz.openbmc_project.FruDevice",