xref: /openbmc/telemetry/tests/src/test_numeric_threshold.cpp (revision 51f0fd501f4b772533271d15cb27d396186a7192)
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, Milliseconds, double>> val)
73     {
74         updates = std::move(val);
75         return *this;
76     }
77 
78     NumericParams&
79         Expected(std::vector<std::tuple<size_t, Milliseconds, 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
92                 << ", Timestamp: " << timestamp.count() << ", Value: " << value
93                 << " }, ";
94         }
95         *os << "Expected: ";
96         for (const auto& [index, timestamp, value] : o.expected)
97         {
98             *os << "{ SensorIndex: " << index
99                 << ", Timestamp: " << timestamp.count() << ", Value: " << value
100                 << " }, ";
101         }
102         *os << " }";
103     }
104 
105     numeric::Direction direction;
106     std::vector<std::tuple<size_t, Milliseconds, double>> updates;
107     std::vector<std::tuple<size_t, Milliseconds, double>> expected;
108 };
109 
110 class TestNumericThresholdNoDwellTime :
111     public TestNumericThreshold,
112     public WithParamInterface<NumericParams>
113 {
114   public:
115     void SetUp() override
116     {
117         makeThreshold(0ms, GetParam().direction, 90.0);
118     }
119 };
120 
121 INSTANTIATE_TEST_SUITE_P(_, TestNumericThresholdNoDwellTime,
122                          Values(NumericParams()
123                                     .Direction(numeric::Direction::increasing)
124                                     .Updates({{0, 1ms, 80.0}, {0, 2ms, 89.0}})
125                                     .Expected({}),
126                                 NumericParams()
127                                     .Direction(numeric::Direction::increasing)
128                                     .Updates({{0, 1ms, 80.0}, {0, 2ms, 91.0}})
129                                     .Expected({{0, 2ms, 91.0}}),
130                                 NumericParams()
131                                     .Direction(numeric::Direction::increasing)
132                                     .Updates({{0, 1ms, 80.0},
133                                               {0, 2ms, 99.0},
134                                               {0, 3ms, 80.0},
135                                               {0, 4ms, 98.0}})
136                                     .Expected({{0, 2ms, 99.0}, {0, 4ms, 98.0}}),
137                                 NumericParams()
138                                     .Direction(numeric::Direction::increasing)
139                                     .Updates({{0, 1ms, 80.0},
140                                               {0, 2ms, 99.0},
141                                               {1, 3ms, 100.0},
142                                               {1, 4ms, 98.0}})
143                                     .Expected({{0, 2ms, 99.0}}),
144                                 NumericParams()
145                                     .Direction(numeric::Direction::decreasing)
146                                     .Updates({{0, 1ms, 100.0}, {0, 2ms, 91.0}})
147                                     .Expected({}),
148                                 NumericParams()
149                                     .Direction(numeric::Direction::decreasing)
150                                     .Updates({{0, 1ms, 100.0}, {0, 2ms, 80.0}})
151                                     .Expected({{0, 2ms, 80.0}}),
152                                 NumericParams()
153                                     .Direction(numeric::Direction::decreasing)
154                                     .Updates({{0, 1ms, 100.0},
155                                               {0, 2ms, 80.0},
156                                               {0, 3ms, 99.0},
157                                               {0, 4ms, 85.0}})
158                                     .Expected({{0, 2ms, 80.0}, {0, 4ms, 85.0}}),
159                                 NumericParams()
160                                     .Direction(numeric::Direction::decreasing)
161                                     .Updates({{0, 1ms, 100.0},
162                                               {0, 2ms, 80.0},
163                                               {1, 3ms, 99.0},
164                                               {1, 4ms, 88.0}})
165                                     .Expected({{0, 2ms, 80.0}, {1, 4ms, 88.0}}),
166                                 NumericParams()
167                                     .Direction(numeric::Direction::either)
168                                     .Updates({{0, 1ms, 98.0}, {0, 2ms, 91.0}})
169                                     .Expected({}),
170                                 NumericParams()
171                                     .Direction(numeric::Direction::either)
172                                     .Updates({{0, 1ms, 100.0},
173                                               {0, 2ms, 80.0},
174                                               {0, 3ms, 85.0},
175                                               {0, 4ms, 91.0}})
176                                     .Expected({{0, 2ms, 80.0}, {0, 4ms, 91.0}}),
177                                 NumericParams()
178                                     .Direction(numeric::Direction::either)
179                                     .Updates({{0, 1ms, 100.0},
180                                               {1, 2ms, 80.0},
181                                               {0, 3ms, 85.0},
182                                               {1, 4ms, 91.0}})
183                                     .Expected({{0, 3ms, 85.0},
184                                                {1, 4ms, 91.0}})));
185 
186 TEST_P(TestNumericThresholdNoDwellTime, senorsIsUpdatedMultipleTimes)
187 {
188     InSequence seq;
189     for (const auto& [index, timestamp, value] : GetParam().expected)
190     {
191         EXPECT_CALL(actionMock, commit(sensorNames[index], timestamp, value));
192     }
193 
194     sut->initialize();
195     for (const auto& [index, timestamp, value] : GetParam().updates)
196     {
197         sut->sensorUpdated(*sensorMocks[index], timestamp, value);
198     }
199 }
200 
201 class TestNumericThresholdWithDwellTime :
202     public TestNumericThreshold,
203     public WithParamInterface<NumericParams>
204 {
205   public:
206     void SetUp() override
207     {
208         makeThreshold(2ms, GetParam().direction, 90.0);
209     }
210 
211     void sleep()
212     {
213         DbusEnvironment::sleepFor(4ms);
214     }
215 };
216 
217 INSTANTIATE_TEST_SUITE_P(_, TestNumericThresholdWithDwellTime,
218                          Values(NumericParams()
219                                     .Direction(numeric::Direction::increasing)
220                                     .Updates({{0, 1ms, 80.0}, {0, 2ms, 89.0}})
221                                     .Expected({}),
222                                 NumericParams()
223                                     .Direction(numeric::Direction::increasing)
224                                     .Updates({{0, 1ms, 80.0}, {0, 2ms, 91.0}})
225                                     .Expected({{0, 2ms, 91.0}}),
226                                 NumericParams()
227                                     .Direction(numeric::Direction::increasing)
228                                     .Updates({{0, 1ms, 80.0},
229                                               {0, 2ms, 99.0},
230                                               {0, 3ms, 80.0},
231                                               {0, 4ms, 98.0}})
232                                     .Expected({{0, 2ms, 99.0}, {0, 4ms, 98.0}}),
233                                 NumericParams()
234                                     .Direction(numeric::Direction::increasing)
235                                     .Updates({{0, 1ms, 80.0},
236                                               {1, 2ms, 99.0},
237                                               {0, 3ms, 100.0},
238                                               {1, 4ms, 86.0}})
239                                     .Expected({{0, 3ms, 100.0}}),
240                                 NumericParams()
241                                     .Direction(numeric::Direction::decreasing)
242                                     .Updates({{0, 1ms, 100.0}, {0, 2ms, 91.0}})
243                                     .Expected({}),
244                                 NumericParams()
245                                     .Direction(numeric::Direction::decreasing)
246                                     .Updates({{0, 1ms, 100.0}, {0, 2ms, 80.0}})
247                                     .Expected({{0, 2ms, 80.0}}),
248                                 NumericParams()
249                                     .Direction(numeric::Direction::decreasing)
250                                     .Updates({{0, 1ms, 100.0},
251                                               {0, 2ms, 80.0},
252                                               {0, 3ms, 99.0},
253                                               {0, 4ms, 85.0}})
254                                     .Expected({{0, 2ms, 80.0}, {0, 4ms, 85.0}}),
255                                 NumericParams()
256                                     .Direction(numeric::Direction::decreasing)
257                                     .Updates({{0, 1ms, 100.0},
258                                               {0, 2ms, 80.0},
259                                               {1, 3ms, 99.0},
260                                               {1, 4ms, 88.0}})
261                                     .Expected({{0, 2ms, 80.0}, {1, 4ms, 88.0}}),
262                                 NumericParams()
263                                     .Direction(numeric::Direction::either)
264                                     .Updates({{0, 1ms, 98.0}, {0, 2ms, 91.0}})
265                                     .Expected({}),
266                                 NumericParams()
267                                     .Direction(numeric::Direction::either)
268                                     .Updates({{0, 1ms, 100.0},
269                                               {0, 2ms, 80.0},
270                                               {0, 3ms, 85.0},
271                                               {0, 4ms, 91.0}})
272                                     .Expected({{0, 2ms, 80.0}, {0, 4ms, 91.0}}),
273                                 NumericParams()
274                                     .Direction(numeric::Direction::either)
275                                     .Updates({{0, 1ms, 100.0},
276                                               {1, 2ms, 80.0},
277                                               {0, 3ms, 85.0},
278                                               {1, 4ms, 91.0}})
279                                     .Expected({{0, 3ms, 85.0},
280                                                {1, 4ms, 91.0}})));
281 
282 TEST_P(TestNumericThresholdWithDwellTime,
283        senorsIsUpdatedMultipleTimesSleepAfterEveryUpdate)
284 {
285     InSequence seq;
286     for (const auto& [index, timestamp, value] : GetParam().expected)
287     {
288         EXPECT_CALL(actionMock, commit(sensorNames[index], timestamp, value));
289     }
290 
291     sut->initialize();
292     for (const auto& [index, timestamp, value] : GetParam().updates)
293     {
294         sut->sensorUpdated(*sensorMocks[index], timestamp, value);
295         sleep();
296     }
297 }
298 
299 class TestNumericThresholdWithDwellTime2 :
300     public TestNumericThreshold,
301     public WithParamInterface<NumericParams>
302 {
303   public:
304     void SetUp() override
305     {
306         makeThreshold(2ms, GetParam().direction, 90.0);
307     }
308 
309     void sleep()
310     {
311         DbusEnvironment::sleepFor(4ms);
312     }
313 };
314 
315 INSTANTIATE_TEST_SUITE_P(_, TestNumericThresholdWithDwellTime2,
316                          Values(NumericParams()
317                                     .Direction(numeric::Direction::increasing)
318                                     .Updates({{0, 1ms, 80.0}, {0, 2ms, 89.0}})
319                                     .Expected({}),
320                                 NumericParams()
321                                     .Direction(numeric::Direction::increasing)
322                                     .Updates({{0, 1ms, 80.0}, {0, 2ms, 91.0}})
323                                     .Expected({{0, 2ms, 91.0}}),
324                                 NumericParams()
325                                     .Direction(numeric::Direction::increasing)
326                                     .Updates({{0, 1ms, 80.0},
327                                               {0, 2ms, 99.0},
328                                               {0, 3ms, 80.0},
329                                               {0, 4ms, 98.0}})
330                                     .Expected({{0, 4ms, 98.0}}),
331                                 NumericParams()
332                                     .Direction(numeric::Direction::increasing)
333                                     .Updates({{0, 1ms, 80.0},
334                                               {1, 2ms, 99.0},
335                                               {0, 3ms, 100.0},
336                                               {1, 4ms, 98.0}})
337                                     .Expected({{0, 3ms, 100.0}}),
338                                 NumericParams()
339                                     .Direction(numeric::Direction::decreasing)
340                                     .Updates({{0, 1ms, 100.0}, {0, 2ms, 91.0}})
341                                     .Expected({}),
342                                 NumericParams()
343                                     .Direction(numeric::Direction::decreasing)
344                                     .Updates({{0, 1ms, 100.0}, {0, 2ms, 80.0}})
345                                     .Expected({{0, 2ms, 80.0}}),
346                                 NumericParams()
347                                     .Direction(numeric::Direction::decreasing)
348                                     .Updates({{0, 1ms, 100.0},
349                                               {0, 2ms, 80.0},
350                                               {0, 3ms, 99.0},
351                                               {0, 4ms, 85.0}})
352                                     .Expected({{0, 4ms, 85.0}}),
353                                 NumericParams()
354                                     .Direction(numeric::Direction::decreasing)
355                                     .Updates({{0, 1ms, 100.0},
356                                               {0, 2ms, 80.0},
357                                               {1, 3ms, 99.0},
358                                               {1, 4ms, 88.0}})
359                                     .Expected({{0, 2ms, 80.0}, {1, 4ms, 88.0}}),
360                                 NumericParams()
361                                     .Direction(numeric::Direction::either)
362                                     .Updates({{0, 1ms, 98.0}, {0, 2ms, 91.0}})
363                                     .Expected({}),
364                                 NumericParams()
365                                     .Direction(numeric::Direction::either)
366                                     .Updates({{0, 1ms, 100.0},
367                                               {0, 2ms, 80.0},
368                                               {0, 3ms, 85.0},
369                                               {0, 4ms, 91.0}})
370                                     .Expected({{0, 4ms, 91.0}}),
371                                 NumericParams()
372                                     .Direction(numeric::Direction::either)
373                                     .Updates({{0, 1ms, 100.0},
374                                               {1, 2ms, 80.0},
375                                               {0, 3ms, 85.0},
376                                               {1, 4ms, 91.0}})
377                                     .Expected({{0, 3ms, 85.0},
378                                                {1, 4ms, 91.0}})));
379 
380 TEST_P(TestNumericThresholdWithDwellTime2,
381        senorsIsUpdatedMultipleTimesSleepAfterLastUpdate)
382 {
383     InSequence seq;
384     for (const auto& [index, timestamp, value] : GetParam().expected)
385     {
386         EXPECT_CALL(actionMock, commit(sensorNames[index], timestamp, value));
387     }
388 
389     sut->initialize();
390     for (const auto& [index, timestamp, value] : GetParam().updates)
391     {
392         sut->sensorUpdated(*sensorMocks[index], timestamp, value);
393     }
394     sleep();
395 }
396