xref: /openbmc/phosphor-health-monitor/test/test_health_metric_collection.cpp (revision ce8b5ae4e7fc1c88cdd85dab8c007cd14408d93f)
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 
SetUp()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 
updateThreshold(ThresholdIntf::Bound bound,double value)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 
createCollection()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 
TEST_F(HealthMetricCollectionTest,TestCreation)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 
TEST_F(HealthMetricCollectionTest,TestThresholdAsserted)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