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