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(double value) 58 { 59 for (auto& [key, values] : configs) 60 { 61 for (auto& config : values) 62 { 63 for (auto& threshold : config.thresholds) 64 { 65 threshold.second.value = value; 66 } 67 } 68 } 69 } 70 71 void createCollection() 72 { 73 std::map<MetricIntf::Type, 74 std::unique_ptr<CollectionIntf::HealthMetricCollection>> 75 collections; 76 MetricIntf::paths_t bmcPaths = {}; 77 for (const auto& [type, collectionConfig] : configs) 78 { 79 collections[type] = 80 std::make_unique<CollectionIntf::HealthMetricCollection>( 81 bus, type, collectionConfig, bmcPaths); 82 collections[type]->read(); 83 } 84 } 85 }; 86 87 TEST_F(HealthMetricCollectionTest, TestCreation) 88 { 89 // Change threshold value to 100 to avoid threshold assertion 90 updateThreshold(100); 91 92 EXPECT_CALL(sdbusMock, 93 sd_bus_emit_properties_changed_strv( 94 IsNull(), NotNull(), StrEq(valueInterface), NotNull())) 95 .WillRepeatedly(Invoke( 96 [&]([[maybe_unused]] sd_bus* bus, [[maybe_unused]] const char* path, 97 [[maybe_unused]] const char* interface, const char** names) { 98 // Test no signal generation for metric init properties 99 const std::set<std::string> metricInitProperties = {"MaxValue", 100 "MinValue", "Unit"}; 101 EXPECT_THAT(metricInitProperties, 102 testing::Not(testing::Contains(names[0]))); 103 // Test signal generated for Value property set 104 const std::set<std::string> metricSetProperties = {"Value"}; 105 EXPECT_THAT(metricSetProperties, testing::Contains(names[0])); 106 return 0; 107 })); 108 109 EXPECT_CALL(sdbusMock, 110 sd_bus_emit_properties_changed_strv( 111 IsNull(), NotNull(), StrEq(thresholdInterface), NotNull())) 112 .WillRepeatedly(Invoke( 113 [&]([[maybe_unused]] sd_bus* bus, [[maybe_unused]] const char* path, 114 [[maybe_unused]] const char* interface, const char** names) { 115 // Test no signal generation for threshold init properties 116 const std::set<std::string> thresholdProperties = {"Value", "Asserted"}; 117 EXPECT_THAT(thresholdProperties, 118 testing::Not(testing::Contains(names[0]))); 119 return 0; 120 })); 121 122 createCollection(); 123 } 124 125 TEST_F(HealthMetricCollectionTest, TestThresholdAsserted) 126 { 127 // Change threshold value to 0 to trigger threshold assertion 128 updateThreshold(0); 129 130 // Test metric value property change 131 EXPECT_CALL(sdbusMock, 132 sd_bus_emit_properties_changed_strv( 133 IsNull(), NotNull(), StrEq(valueInterface), NotNull())) 134 .WillRepeatedly(Invoke( 135 [&]([[maybe_unused]] sd_bus* bus, [[maybe_unused]] const char* path, 136 [[maybe_unused]] const char* interface, const char** names) { 137 EXPECT_THAT("Value", StrEq(names[0])); 138 return 0; 139 })); 140 141 // Test threshold asserted property change 142 EXPECT_CALL(sdbusMock, 143 sd_bus_emit_properties_changed_strv( 144 IsNull(), NotNull(), StrEq(thresholdInterface), NotNull())) 145 .WillRepeatedly(Invoke( 146 [&]([[maybe_unused]] sd_bus* bus, [[maybe_unused]] const char* path, 147 [[maybe_unused]] const char* interface, const char** names) { 148 EXPECT_THAT("Asserted", StrEq(names[0])); 149 return 0; 150 })); 151 152 // Test AssertionChanged signal generation 153 EXPECT_CALL(sdbusMock, 154 sd_bus_message_new_signal(IsNull(), NotNull(), NotNull(), 155 StrEq(thresholdInterface), 156 StrEq("AssertionChanged"))) 157 .Times(11); 158 159 createCollection(); 160 } 161