1 #include "health_metric_collection.hpp" 2 3 #include <sdbusplus/test/sdbus_mock.hpp> 4 #include <xyz/openbmc_project/Metric/Value/server.hpp> 5 6 #include <gtest/gtest.h> 7 8 namespace ConfigIntf = phosphor::health::metric::config; 9 namespace MetricIntf = phosphor::health::metric; 10 namespace CollectionIntf = phosphor::health::metric::collection; 11 12 using PathInterface = 13 sdbusplus::common::xyz::openbmc_project::metric::Value::namespace_path; 14 using ThresholdIntf = 15 sdbusplus::server::xyz::openbmc_project::common::Threshold; 16 using ::testing::Invoke; 17 using ::testing::IsNull; 18 using ::testing::NotNull; 19 using ::testing::StrEq; 20 21 class HealthMetricCollectionTest : public ::testing::Test 22 { 23 public: 24 sdbusplus::SdBusMock sdbusMock; 25 sdbusplus::bus_t bus = sdbusplus::get_mocked_new(&sdbusMock); 26 27 static constexpr auto busName = "xyz.openbmc_project.test.HealthMon"; 28 static constexpr auto objPath = "/xyz/openbmc_project/sdbusplus/test"; 29 const std::string valueInterface = 30 sdbusplus::common::xyz::openbmc_project::metric::Value::interface; 31 const std::string thresholdInterface = 32 sdbusplus::common::xyz::openbmc_project::common::Threshold::interface; 33 ConfigIntf::HealthMetric::map_t configs; 34 35 void SetUp() override 36 { 37 sdbusplus::server::manager_t objManager(bus, objPath); 38 bus.request_name(busName); 39 40 configs = ConfigIntf::getHealthMetricConfigs(); 41 EXPECT_THAT(configs.size(), testing::Ge(1)); 42 // Update the health metric window size to 1 and path for test purposes 43 for (auto& [key, values] : configs) 44 { 45 for (auto& config : values) 46 { 47 config.windowSize = 1; 48 if (key == MetricIntf::Type::storage && 49 config.subType == MetricIntf::SubType::storageReadWrite) 50 { 51 config.path = "/tmp"; 52 } 53 } 54 } 55 } 56 57 void updateThreshold(ThresholdIntf::Bound bound, double value) 58 { 59 for (auto& [key, values] : configs) 60 { 61 for (auto& config : values) 62 { 63 for (auto& threshold : config.thresholds) 64 { 65 if (get<ThresholdIntf::Bound>(threshold.first) == bound) 66 { 67 threshold.second.value = value; 68 } 69 } 70 } 71 } 72 } 73 74 void createCollection() 75 { 76 std::map<MetricIntf::Type, 77 std::unique_ptr<CollectionIntf::HealthMetricCollection>> 78 collections; 79 MetricIntf::paths_t bmcPaths = {}; 80 for (const auto& [type, collectionConfig] : configs) 81 { 82 collections[type] = 83 std::make_unique<CollectionIntf::HealthMetricCollection>( 84 bus, type, collectionConfig, bmcPaths); 85 collections[type]->read(); 86 } 87 } 88 }; 89 90 TEST_F(HealthMetricCollectionTest, TestCreation) 91 { 92 // Change threshold values to avoid threshold assertion 93 updateThreshold(ThresholdIntf::Bound::Upper, 100); 94 updateThreshold(ThresholdIntf::Bound::Lower, 0); 95 96 EXPECT_CALL(sdbusMock, 97 sd_bus_emit_properties_changed_strv( 98 IsNull(), NotNull(), StrEq(valueInterface), NotNull())) 99 .WillRepeatedly(Invoke( 100 [&]([[maybe_unused]] sd_bus* bus, [[maybe_unused]] const char* path, 101 [[maybe_unused]] const char* interface, const char** names) { 102 // Test no signal generation for metric init properties 103 const std::set<std::string> metricInitProperties = {"MaxValue", 104 "MinValue", "Unit"}; 105 EXPECT_THAT(metricInitProperties, 106 testing::Not(testing::Contains(names[0]))); 107 // Test signal generated for Value property set 108 const std::set<std::string> metricSetProperties = {"Value"}; 109 EXPECT_THAT(metricSetProperties, testing::Contains(names[0])); 110 return 0; 111 })); 112 113 EXPECT_CALL(sdbusMock, 114 sd_bus_emit_properties_changed_strv( 115 IsNull(), NotNull(), StrEq(thresholdInterface), NotNull())) 116 .WillRepeatedly(Invoke( 117 [&]([[maybe_unused]] sd_bus* bus, [[maybe_unused]] const char* path, 118 [[maybe_unused]] const char* interface, const char** names) { 119 // Test no signal generation for threshold init properties 120 const std::set<std::string> thresholdProperties = {"Value", "Asserted"}; 121 EXPECT_THAT(thresholdProperties, 122 testing::Not(testing::Contains(names[0]))); 123 return 0; 124 })); 125 126 createCollection(); 127 } 128 129 TEST_F(HealthMetricCollectionTest, TestThresholdAsserted) 130 { 131 // Change threshold values to trigger threshold assertion 132 updateThreshold(ThresholdIntf::Bound::Upper, 0); 133 updateThreshold(ThresholdIntf::Bound::Lower, 100); 134 135 // Test metric value property change 136 EXPECT_CALL(sdbusMock, 137 sd_bus_emit_properties_changed_strv( 138 IsNull(), NotNull(), StrEq(valueInterface), NotNull())) 139 .WillRepeatedly(Invoke( 140 [&]([[maybe_unused]] sd_bus* bus, [[maybe_unused]] const char* path, 141 [[maybe_unused]] const char* interface, const char** names) { 142 EXPECT_THAT("Value", StrEq(names[0])); 143 return 0; 144 })); 145 146 // Test threshold asserted property change 147 EXPECT_CALL(sdbusMock, 148 sd_bus_emit_properties_changed_strv( 149 IsNull(), NotNull(), StrEq(thresholdInterface), NotNull())) 150 .WillRepeatedly(Invoke( 151 [&]([[maybe_unused]] sd_bus* bus, [[maybe_unused]] const char* path, 152 [[maybe_unused]] const char* interface, const char** names) { 153 EXPECT_THAT("Asserted", StrEq(names[0])); 154 return 0; 155 })); 156 157 // Test AssertionChanged signal generation 158 EXPECT_CALL(sdbusMock, 159 sd_bus_message_new_signal(IsNull(), NotNull(), NotNull(), 160 StrEq(thresholdInterface), 161 StrEq("AssertionChanged"))) 162 .Times(8); 163 164 createCollection(); 165 } 166