xref: /openbmc/telemetry/tests/src/test_numeric_threshold.cpp (revision dcc4e1936173a93251a02066432bc2bcbc386240)
1 #include "dbus_environment.hpp"
2 #include "helpers.hpp"
3 #include "mocks/sensor_mock.hpp"
4 #include "mocks/trigger_action_mock.hpp"
5 #include "numeric_threshold.hpp"
6 #include "utils/conv_container.hpp"
7 
8 #include <gmock/gmock.h>
9 
10 using namespace testing;
11 using namespace std::chrono_literals;
12 
13 class TestNumericThreshold : public Test
14 {
15   public:
16     std::vector<std::shared_ptr<SensorMock>> sensorMocks = {
17         std::make_shared<NiceMock<SensorMock>>(),
18         std::make_shared<NiceMock<SensorMock>>()};
19     std::vector<std::string> sensorNames = {"Sensor1", "Sensor2"};
20     std::unique_ptr<TriggerActionMock> actionMockPtr =
21         std::make_unique<StrictMock<TriggerActionMock>>();
22     TriggerActionMock& actionMock = *actionMockPtr;
23     std::shared_ptr<NumericThreshold> sut;
24 
25     void makeThreshold(Milliseconds dwellTime, numeric::Direction direction,
26                        double thresholdValue)
27     {
28         std::vector<std::unique_ptr<interfaces::TriggerAction>> actions;
29         actions.push_back(std::move(actionMockPtr));
30 
31         sut = std::make_shared<NumericThreshold>(
32             DbusEnvironment::getIoc(),
33             utils::convContainer<std::shared_ptr<interfaces::Sensor>>(
34                 sensorMocks),
35             sensorNames, std::move(actions), dwellTime, direction,
36             thresholdValue);
37     }
38 
39     void SetUp() override
40     {
41         makeThreshold(0ms, numeric::Direction::increasing, 90.0);
42     }
43 };
44 
45 TEST_F(TestNumericThreshold, initializeThresholdExpectAllSensorsAreRegistered)
46 {
47     for (auto& sensor : sensorMocks)
48     {
49         EXPECT_CALL(*sensor,
50                     registerForUpdates(Truly([sut = sut.get()](const auto& x) {
51                         return x.lock().get() == sut;
52                     })));
53     }
54 
55     sut->initialize();
56 }
57 
58 TEST_F(TestNumericThreshold, thresholdIsNotInitializeExpectNoActionCommit)
59 {
60     EXPECT_CALL(actionMock, commit(_, _, _)).Times(0);
61 }
62 
63 struct NumericParams
64 {
65     NumericParams& Direction(numeric::Direction val)
66     {
67         direction = val;
68         return *this;
69     }
70 
71     NumericParams&
72         Updates(std::vector<std::tuple<size_t, uint64_t, double>> val)
73     {
74         updates = std::move(val);
75         return *this;
76     }
77 
78     NumericParams&
79         Expected(std::vector<std::tuple<size_t, uint64_t, double>> val)
80     {
81         expected = std::move(val);
82         return *this;
83     }
84 
85     friend void PrintTo(const NumericParams& o, std::ostream* os)
86     {
87         *os << "{ Direction: " << static_cast<int>(o.direction)
88             << ", Updates: ";
89         for (const auto& [index, timestamp, value] : o.updates)
90         {
91             *os << "{ SensorIndex: " << index << ", Timestamp: " << timestamp
92                 << ", Value: " << value << " }, ";
93         }
94         *os << "Expected: ";
95         for (const auto& [index, timestamp, value] : o.expected)
96         {
97             *os << "{ SensorIndex: " << index << ", Timestamp: " << timestamp
98                 << ", Value: " << value << " }, ";
99         }
100         *os << " }";
101     }
102 
103     numeric::Direction direction;
104     std::vector<std::tuple<size_t, uint64_t, double>> updates;
105     std::vector<std::tuple<size_t, uint64_t, double>> expected;
106 };
107 
108 class TestNumericThresholdNoDwellTime :
109     public TestNumericThreshold,
110     public WithParamInterface<NumericParams>
111 {
112   public:
113     void SetUp() override
114     {
115         makeThreshold(0ms, GetParam().direction, 90.0);
116     }
117 };
118 
119 INSTANTIATE_TEST_SUITE_P(
120     _, TestNumericThresholdNoDwellTime,
121     Values(
122         NumericParams()
123             .Direction(numeric::Direction::increasing)
124             .Updates({{0, 1, 80.0}, {0, 2, 89.0}})
125             .Expected({}),
126         NumericParams()
127             .Direction(numeric::Direction::increasing)
128             .Updates({{0, 1, 80.0}, {0, 2, 91.0}})
129             .Expected({{0, 2, 91.0}}),
130         NumericParams()
131             .Direction(numeric::Direction::increasing)
132             .Updates({{0, 1, 80.0}, {0, 2, 99.0}, {0, 3, 80.0}, {0, 4, 98.0}})
133             .Expected({{0, 2, 99.0}, {0, 4, 98.0}}),
134         NumericParams()
135             .Direction(numeric::Direction::increasing)
136             .Updates({{0, 1, 80.0}, {0, 2, 99.0}, {1, 3, 100.0}, {1, 4, 98.0}})
137             .Expected({{0, 2, 99.0}}),
138         NumericParams()
139             .Direction(numeric::Direction::decreasing)
140             .Updates({{0, 1, 100.0}, {0, 2, 91.0}})
141             .Expected({}),
142         NumericParams()
143             .Direction(numeric::Direction::decreasing)
144             .Updates({{0, 1, 100.0}, {0, 2, 80.0}})
145             .Expected({{0, 2, 80.0}}),
146         NumericParams()
147             .Direction(numeric::Direction::decreasing)
148             .Updates({{0, 1, 100.0}, {0, 2, 80.0}, {0, 3, 99.0}, {0, 4, 85.0}})
149             .Expected({{0, 2, 80.0}, {0, 4, 85.0}}),
150         NumericParams()
151             .Direction(numeric::Direction::decreasing)
152             .Updates({{0, 1, 100.0}, {0, 2, 80.0}, {1, 3, 99.0}, {1, 4, 88.0}})
153             .Expected({{0, 2, 80.0}, {1, 4, 88.0}}),
154         NumericParams()
155             .Direction(numeric::Direction::either)
156             .Updates({{0, 1, 98.0}, {0, 2, 91.0}})
157             .Expected({}),
158         NumericParams()
159             .Direction(numeric::Direction::either)
160             .Updates({{0, 1, 100.0}, {0, 2, 80.0}, {0, 3, 85.0}, {0, 4, 91.0}})
161             .Expected({{0, 2, 80.0}, {0, 4, 91.0}}),
162         NumericParams()
163             .Direction(numeric::Direction::either)
164             .Updates({{0, 1, 100.0}, {1, 2, 80.0}, {0, 3, 85.0}, {1, 4, 91.0}})
165             .Expected({{0, 3, 85.0}, {1, 4, 91.0}})));
166 
167 TEST_P(TestNumericThresholdNoDwellTime, senorsIsUpdatedMultipleTimes)
168 {
169     InSequence seq;
170     for (const auto& [index, timestamp, value] : GetParam().expected)
171     {
172         EXPECT_CALL(actionMock, commit(sensorNames[index], timestamp, value));
173     }
174 
175     sut->initialize();
176     for (const auto& [index, timestamp, value] : GetParam().updates)
177     {
178         sut->sensorUpdated(*sensorMocks[index], timestamp, value);
179     }
180 }
181 
182 class TestNumericThresholdWithDwellTime :
183     public TestNumericThreshold,
184     public WithParamInterface<NumericParams>
185 {
186   public:
187     void SetUp() override
188     {
189         makeThreshold(2ms, GetParam().direction, 90.0);
190     }
191 
192     void sleep()
193     {
194         DbusEnvironment::sleepFor(4ms);
195     }
196 };
197 
198 INSTANTIATE_TEST_SUITE_P(
199     _, TestNumericThresholdWithDwellTime,
200     Values(
201         NumericParams()
202             .Direction(numeric::Direction::increasing)
203             .Updates({{0, 1, 80.0}, {0, 2, 89.0}})
204             .Expected({}),
205         NumericParams()
206             .Direction(numeric::Direction::increasing)
207             .Updates({{0, 1, 80.0}, {0, 2, 91.0}})
208             .Expected({{0, 2, 91.0}}),
209         NumericParams()
210             .Direction(numeric::Direction::increasing)
211             .Updates({{0, 1, 80.0}, {0, 2, 99.0}, {0, 3, 80.0}, {0, 4, 98.0}})
212             .Expected({{0, 2, 99.0}, {0, 4, 98.0}}),
213         NumericParams()
214             .Direction(numeric::Direction::increasing)
215             .Updates({{0, 1, 80.0}, {1, 2, 99.0}, {0, 3, 100.0}, {1, 4, 86.0}})
216             .Expected({{0, 3, 100.0}}),
217         NumericParams()
218             .Direction(numeric::Direction::decreasing)
219             .Updates({{0, 1, 100.0}, {0, 2, 91.0}})
220             .Expected({}),
221         NumericParams()
222             .Direction(numeric::Direction::decreasing)
223             .Updates({{0, 1, 100.0}, {0, 2, 80.0}})
224             .Expected({{0, 2, 80.0}}),
225         NumericParams()
226             .Direction(numeric::Direction::decreasing)
227             .Updates({{0, 1, 100.0}, {0, 2, 80.0}, {0, 3, 99.0}, {0, 4, 85.0}})
228             .Expected({{0, 2, 80.0}, {0, 4, 85.0}}),
229         NumericParams()
230             .Direction(numeric::Direction::decreasing)
231             .Updates({{0, 1, 100.0}, {0, 2, 80.0}, {1, 3, 99.0}, {1, 4, 88.0}})
232             .Expected({{0, 2, 80.0}, {1, 4, 88.0}}),
233         NumericParams()
234             .Direction(numeric::Direction::either)
235             .Updates({{0, 1, 98.0}, {0, 2, 91.0}})
236             .Expected({}),
237         NumericParams()
238             .Direction(numeric::Direction::either)
239             .Updates({{0, 1, 100.0}, {0, 2, 80.0}, {0, 3, 85.0}, {0, 4, 91.0}})
240             .Expected({{0, 2, 80.0}, {0, 4, 91.0}}),
241         NumericParams()
242             .Direction(numeric::Direction::either)
243             .Updates({{0, 1, 100.0}, {1, 2, 80.0}, {0, 3, 85.0}, {1, 4, 91.0}})
244             .Expected({{0, 3, 85.0}, {1, 4, 91.0}})));
245 
246 TEST_P(TestNumericThresholdWithDwellTime,
247        senorsIsUpdatedMultipleTimesSleepAfterEveryUpdate)
248 {
249     InSequence seq;
250     for (const auto& [index, timestamp, value] : GetParam().expected)
251     {
252         EXPECT_CALL(actionMock, commit(sensorNames[index], timestamp, value));
253     }
254 
255     sut->initialize();
256     for (const auto& [index, timestamp, value] : GetParam().updates)
257     {
258         sut->sensorUpdated(*sensorMocks[index], timestamp, value);
259         sleep();
260     }
261 }
262 
263 class TestNumericThresholdWithDwellTime2 :
264     public TestNumericThreshold,
265     public WithParamInterface<NumericParams>
266 {
267   public:
268     void SetUp() override
269     {
270         makeThreshold(2ms, GetParam().direction, 90.0);
271     }
272 
273     void sleep()
274     {
275         DbusEnvironment::sleepFor(4ms);
276     }
277 };
278 
279 INSTANTIATE_TEST_SUITE_P(
280     _, TestNumericThresholdWithDwellTime2,
281     Values(
282         NumericParams()
283             .Direction(numeric::Direction::increasing)
284             .Updates({{0, 1, 80.0}, {0, 2, 89.0}})
285             .Expected({}),
286         NumericParams()
287             .Direction(numeric::Direction::increasing)
288             .Updates({{0, 1, 80.0}, {0, 2, 91.0}})
289             .Expected({{0, 2, 91.0}}),
290         NumericParams()
291             .Direction(numeric::Direction::increasing)
292             .Updates({{0, 1, 80.0}, {0, 2, 99.0}, {0, 3, 80.0}, {0, 4, 98.0}})
293             .Expected({{0, 4, 98.0}}),
294         NumericParams()
295             .Direction(numeric::Direction::increasing)
296             .Updates({{0, 1, 80.0}, {1, 2, 99.0}, {0, 3, 100.0}, {1, 4, 98.0}})
297             .Expected({{0, 3, 100.0}}),
298         NumericParams()
299             .Direction(numeric::Direction::decreasing)
300             .Updates({{0, 1, 100.0}, {0, 2, 91.0}})
301             .Expected({}),
302         NumericParams()
303             .Direction(numeric::Direction::decreasing)
304             .Updates({{0, 1, 100.0}, {0, 2, 80.0}})
305             .Expected({{0, 2, 80.0}}),
306         NumericParams()
307             .Direction(numeric::Direction::decreasing)
308             .Updates({{0, 1, 100.0}, {0, 2, 80.0}, {0, 3, 99.0}, {0, 4, 85.0}})
309             .Expected({{0, 4, 85.0}}),
310         NumericParams()
311             .Direction(numeric::Direction::decreasing)
312             .Updates({{0, 1, 100.0}, {0, 2, 80.0}, {1, 3, 99.0}, {1, 4, 88.0}})
313             .Expected({{0, 2, 80.0}, {1, 4, 88.0}}),
314         NumericParams()
315             .Direction(numeric::Direction::either)
316             .Updates({{0, 1, 98.0}, {0, 2, 91.0}})
317             .Expected({}),
318         NumericParams()
319             .Direction(numeric::Direction::either)
320             .Updates({{0, 1, 100.0}, {0, 2, 80.0}, {0, 3, 85.0}, {0, 4, 91.0}})
321             .Expected({{0, 4, 91.0}}),
322         NumericParams()
323             .Direction(numeric::Direction::either)
324             .Updates({{0, 1, 100.0}, {1, 2, 80.0}, {0, 3, 85.0}, {1, 4, 91.0}})
325             .Expected({{0, 3, 85.0}, {1, 4, 91.0}})));
326 
327 TEST_P(TestNumericThresholdWithDwellTime2,
328        senorsIsUpdatedMultipleTimesSleepAfterLastUpdate)
329 {
330     InSequence seq;
331     for (const auto& [index, timestamp, value] : GetParam().expected)
332     {
333         EXPECT_CALL(actionMock, commit(sensorNames[index], timestamp, value));
334     }
335 
336     sut->initialize();
337     for (const auto& [index, timestamp, value] : GetParam().updates)
338     {
339         sut->sensorUpdated(*sensorMocks[index], timestamp, value);
340     }
341     sleep();
342 }
343