blob: 65c976ce91d926ed9053a6cdeddb0b9e1d23a4ed [file] [log] [blame]
Wludzik, Jozef1477fe62021-01-02 11:56:10 +01001#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
10using namespace testing;
11using namespace std::chrono_literals;
12
13class 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
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +000025 void makeThreshold(Milliseconds dwellTime, numeric::Direction direction,
Szymon Dompke94f71c52021-12-10 07:16:33 +010026 double thresholdValue,
27 numeric::Type type = numeric::Type::lowerWarning)
Wludzik, Jozef1477fe62021-01-02 11:56:10 +010028 {
29 std::vector<std::unique_ptr<interfaces::TriggerAction>> actions;
30 actions.push_back(std::move(actionMockPtr));
31
32 sut = std::make_shared<NumericThreshold>(
33 DbusEnvironment::getIoc(),
34 utils::convContainer<std::shared_ptr<interfaces::Sensor>>(
35 sensorMocks),
Szymon Dompke94f71c52021-12-10 07:16:33 +010036 std::move(actions), dwellTime, direction, thresholdValue, type);
Wludzik, Jozef1477fe62021-01-02 11:56:10 +010037 }
38
39 void SetUp() override
40 {
Szymon Dompke94f71c52021-12-10 07:16:33 +010041 for (size_t idx = 0; idx < sensorMocks.size(); idx++)
42 {
43 ON_CALL(*sensorMocks.at(idx), getName())
44 .WillByDefault(Return(sensorNames[idx]));
45 }
46
47 makeThreshold(0ms, numeric::Direction::increasing, 90.0,
48 numeric::Type::upperCritical);
Wludzik, Jozef1477fe62021-01-02 11:56:10 +010049 }
50};
51
52TEST_F(TestNumericThreshold, initializeThresholdExpectAllSensorsAreRegistered)
53{
54 for (auto& sensor : sensorMocks)
55 {
56 EXPECT_CALL(*sensor,
57 registerForUpdates(Truly([sut = sut.get()](const auto& x) {
58 return x.lock().get() == sut;
59 })));
60 }
61
62 sut->initialize();
63}
64
65TEST_F(TestNumericThreshold, thresholdIsNotInitializeExpectNoActionCommit)
66{
67 EXPECT_CALL(actionMock, commit(_, _, _)).Times(0);
68}
69
Szymon Dompke94f71c52021-12-10 07:16:33 +010070TEST_F(TestNumericThreshold, getLabeledParamsReturnsCorrectly)
71{
72 LabeledThresholdParam expected = numeric::LabeledThresholdParam(
73 numeric::Type::upperCritical, 0, numeric::Direction::increasing, 90.0);
74 EXPECT_EQ(sut->getThresholdParam(), expected);
75}
76
Wludzik, Jozef1477fe62021-01-02 11:56:10 +010077struct NumericParams
78{
79 NumericParams& Direction(numeric::Direction val)
80 {
81 direction = val;
82 return *this;
83 }
84
85 NumericParams&
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +010086 Updates(std::vector<std::tuple<size_t, Milliseconds, double>> val)
Wludzik, Jozef1477fe62021-01-02 11:56:10 +010087 {
88 updates = std::move(val);
89 return *this;
90 }
91
92 NumericParams&
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +010093 Expected(std::vector<std::tuple<size_t, Milliseconds, double>> val)
Wludzik, Jozef1477fe62021-01-02 11:56:10 +010094 {
95 expected = std::move(val);
96 return *this;
97 }
98
99 friend void PrintTo(const NumericParams& o, std::ostream* os)
100 {
101 *os << "{ Direction: " << static_cast<int>(o.direction)
102 << ", Updates: ";
103 for (const auto& [index, timestamp, value] : o.updates)
104 {
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100105 *os << "{ SensorIndex: " << index
106 << ", Timestamp: " << timestamp.count() << ", Value: " << value
107 << " }, ";
Wludzik, Jozef1477fe62021-01-02 11:56:10 +0100108 }
109 *os << "Expected: ";
110 for (const auto& [index, timestamp, value] : o.expected)
111 {
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100112 *os << "{ SensorIndex: " << index
113 << ", Timestamp: " << timestamp.count() << ", Value: " << value
114 << " }, ";
Wludzik, Jozef1477fe62021-01-02 11:56:10 +0100115 }
116 *os << " }";
117 }
118
119 numeric::Direction direction;
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100120 std::vector<std::tuple<size_t, Milliseconds, double>> updates;
121 std::vector<std::tuple<size_t, Milliseconds, double>> expected;
Wludzik, Jozef1477fe62021-01-02 11:56:10 +0100122};
123
124class TestNumericThresholdNoDwellTime :
125 public TestNumericThreshold,
126 public WithParamInterface<NumericParams>
127{
128 public:
129 void SetUp() override
130 {
Szymon Dompke94f71c52021-12-10 07:16:33 +0100131 for (size_t idx = 0; idx < sensorMocks.size(); idx++)
132 {
133 ON_CALL(*sensorMocks.at(idx), getName())
134 .WillByDefault(Return(sensorNames[idx]));
135 }
136
Wludzik, Jozef1477fe62021-01-02 11:56:10 +0100137 makeThreshold(0ms, GetParam().direction, 90.0);
138 }
139};
140
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100141INSTANTIATE_TEST_SUITE_P(_, TestNumericThresholdNoDwellTime,
142 Values(NumericParams()
143 .Direction(numeric::Direction::increasing)
144 .Updates({{0, 1ms, 80.0}, {0, 2ms, 89.0}})
145 .Expected({}),
146 NumericParams()
147 .Direction(numeric::Direction::increasing)
148 .Updates({{0, 1ms, 80.0}, {0, 2ms, 91.0}})
149 .Expected({{0, 2ms, 91.0}}),
150 NumericParams()
151 .Direction(numeric::Direction::increasing)
152 .Updates({{0, 1ms, 80.0},
153 {0, 2ms, 99.0},
154 {0, 3ms, 80.0},
155 {0, 4ms, 98.0}})
156 .Expected({{0, 2ms, 99.0}, {0, 4ms, 98.0}}),
157 NumericParams()
158 .Direction(numeric::Direction::increasing)
159 .Updates({{0, 1ms, 80.0},
160 {0, 2ms, 99.0},
161 {1, 3ms, 100.0},
162 {1, 4ms, 98.0}})
163 .Expected({{0, 2ms, 99.0}}),
164 NumericParams()
165 .Direction(numeric::Direction::decreasing)
166 .Updates({{0, 1ms, 100.0}, {0, 2ms, 91.0}})
167 .Expected({}),
168 NumericParams()
169 .Direction(numeric::Direction::decreasing)
170 .Updates({{0, 1ms, 100.0}, {0, 2ms, 80.0}})
171 .Expected({{0, 2ms, 80.0}}),
172 NumericParams()
173 .Direction(numeric::Direction::decreasing)
174 .Updates({{0, 1ms, 100.0},
175 {0, 2ms, 80.0},
176 {0, 3ms, 99.0},
177 {0, 4ms, 85.0}})
178 .Expected({{0, 2ms, 80.0}, {0, 4ms, 85.0}}),
179 NumericParams()
180 .Direction(numeric::Direction::decreasing)
181 .Updates({{0, 1ms, 100.0},
182 {0, 2ms, 80.0},
183 {1, 3ms, 99.0},
184 {1, 4ms, 88.0}})
185 .Expected({{0, 2ms, 80.0}, {1, 4ms, 88.0}}),
186 NumericParams()
187 .Direction(numeric::Direction::either)
188 .Updates({{0, 1ms, 98.0}, {0, 2ms, 91.0}})
189 .Expected({}),
190 NumericParams()
191 .Direction(numeric::Direction::either)
192 .Updates({{0, 1ms, 100.0},
193 {0, 2ms, 80.0},
194 {0, 3ms, 85.0},
195 {0, 4ms, 91.0}})
196 .Expected({{0, 2ms, 80.0}, {0, 4ms, 91.0}}),
197 NumericParams()
198 .Direction(numeric::Direction::either)
199 .Updates({{0, 1ms, 100.0},
200 {1, 2ms, 80.0},
201 {0, 3ms, 85.0},
202 {1, 4ms, 91.0}})
203 .Expected({{0, 3ms, 85.0},
204 {1, 4ms, 91.0}})));
Wludzik, Jozef1477fe62021-01-02 11:56:10 +0100205
206TEST_P(TestNumericThresholdNoDwellTime, senorsIsUpdatedMultipleTimes)
207{
208 InSequence seq;
209 for (const auto& [index, timestamp, value] : GetParam().expected)
210 {
211 EXPECT_CALL(actionMock, commit(sensorNames[index], timestamp, value));
212 }
213
214 sut->initialize();
215 for (const auto& [index, timestamp, value] : GetParam().updates)
216 {
217 sut->sensorUpdated(*sensorMocks[index], timestamp, value);
218 }
219}
220
221class TestNumericThresholdWithDwellTime :
222 public TestNumericThreshold,
223 public WithParamInterface<NumericParams>
224{
225 public:
226 void SetUp() override
227 {
Szymon Dompke94f71c52021-12-10 07:16:33 +0100228 for (size_t idx = 0; idx < sensorMocks.size(); idx++)
229 {
230 ON_CALL(*sensorMocks.at(idx), getName())
231 .WillByDefault(Return(sensorNames[idx]));
232 }
233
Wludzik, Jozef1477fe62021-01-02 11:56:10 +0100234 makeThreshold(2ms, GetParam().direction, 90.0);
235 }
236
237 void sleep()
238 {
239 DbusEnvironment::sleepFor(4ms);
240 }
241};
242
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100243INSTANTIATE_TEST_SUITE_P(_, TestNumericThresholdWithDwellTime,
244 Values(NumericParams()
245 .Direction(numeric::Direction::increasing)
246 .Updates({{0, 1ms, 80.0}, {0, 2ms, 89.0}})
247 .Expected({}),
248 NumericParams()
249 .Direction(numeric::Direction::increasing)
250 .Updates({{0, 1ms, 80.0}, {0, 2ms, 91.0}})
251 .Expected({{0, 2ms, 91.0}}),
252 NumericParams()
253 .Direction(numeric::Direction::increasing)
254 .Updates({{0, 1ms, 80.0},
255 {0, 2ms, 99.0},
256 {0, 3ms, 80.0},
257 {0, 4ms, 98.0}})
258 .Expected({{0, 2ms, 99.0}, {0, 4ms, 98.0}}),
259 NumericParams()
260 .Direction(numeric::Direction::increasing)
261 .Updates({{0, 1ms, 80.0},
262 {1, 2ms, 99.0},
263 {0, 3ms, 100.0},
264 {1, 4ms, 86.0}})
265 .Expected({{0, 3ms, 100.0}}),
266 NumericParams()
267 .Direction(numeric::Direction::decreasing)
268 .Updates({{0, 1ms, 100.0}, {0, 2ms, 91.0}})
269 .Expected({}),
270 NumericParams()
271 .Direction(numeric::Direction::decreasing)
272 .Updates({{0, 1ms, 100.0}, {0, 2ms, 80.0}})
273 .Expected({{0, 2ms, 80.0}}),
274 NumericParams()
275 .Direction(numeric::Direction::decreasing)
276 .Updates({{0, 1ms, 100.0},
277 {0, 2ms, 80.0},
278 {0, 3ms, 99.0},
279 {0, 4ms, 85.0}})
280 .Expected({{0, 2ms, 80.0}, {0, 4ms, 85.0}}),
281 NumericParams()
282 .Direction(numeric::Direction::decreasing)
283 .Updates({{0, 1ms, 100.0},
284 {0, 2ms, 80.0},
285 {1, 3ms, 99.0},
286 {1, 4ms, 88.0}})
287 .Expected({{0, 2ms, 80.0}, {1, 4ms, 88.0}}),
288 NumericParams()
289 .Direction(numeric::Direction::either)
290 .Updates({{0, 1ms, 98.0}, {0, 2ms, 91.0}})
291 .Expected({}),
292 NumericParams()
293 .Direction(numeric::Direction::either)
294 .Updates({{0, 1ms, 100.0},
295 {0, 2ms, 80.0},
296 {0, 3ms, 85.0},
297 {0, 4ms, 91.0}})
298 .Expected({{0, 2ms, 80.0}, {0, 4ms, 91.0}}),
299 NumericParams()
300 .Direction(numeric::Direction::either)
301 .Updates({{0, 1ms, 100.0},
302 {1, 2ms, 80.0},
303 {0, 3ms, 85.0},
304 {1, 4ms, 91.0}})
305 .Expected({{0, 3ms, 85.0},
306 {1, 4ms, 91.0}})));
Wludzik, Jozef1477fe62021-01-02 11:56:10 +0100307
308TEST_P(TestNumericThresholdWithDwellTime,
309 senorsIsUpdatedMultipleTimesSleepAfterEveryUpdate)
310{
311 InSequence seq;
312 for (const auto& [index, timestamp, value] : GetParam().expected)
313 {
314 EXPECT_CALL(actionMock, commit(sensorNames[index], timestamp, value));
315 }
316
317 sut->initialize();
318 for (const auto& [index, timestamp, value] : GetParam().updates)
319 {
320 sut->sensorUpdated(*sensorMocks[index], timestamp, value);
321 sleep();
322 }
323}
324
325class TestNumericThresholdWithDwellTime2 :
326 public TestNumericThreshold,
327 public WithParamInterface<NumericParams>
328{
329 public:
330 void SetUp() override
331 {
Szymon Dompke94f71c52021-12-10 07:16:33 +0100332 for (size_t idx = 0; idx < sensorMocks.size(); idx++)
333 {
334 ON_CALL(*sensorMocks.at(idx), getName())
335 .WillByDefault(Return(sensorNames[idx]));
336 }
337
Wludzik, Jozef1477fe62021-01-02 11:56:10 +0100338 makeThreshold(2ms, GetParam().direction, 90.0);
339 }
340
341 void sleep()
342 {
343 DbusEnvironment::sleepFor(4ms);
344 }
345};
346
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100347INSTANTIATE_TEST_SUITE_P(_, TestNumericThresholdWithDwellTime2,
348 Values(NumericParams()
349 .Direction(numeric::Direction::increasing)
350 .Updates({{0, 1ms, 80.0}, {0, 2ms, 89.0}})
351 .Expected({}),
352 NumericParams()
353 .Direction(numeric::Direction::increasing)
354 .Updates({{0, 1ms, 80.0}, {0, 2ms, 91.0}})
355 .Expected({{0, 2ms, 91.0}}),
356 NumericParams()
357 .Direction(numeric::Direction::increasing)
358 .Updates({{0, 1ms, 80.0},
359 {0, 2ms, 99.0},
360 {0, 3ms, 80.0},
361 {0, 4ms, 98.0}})
362 .Expected({{0, 4ms, 98.0}}),
363 NumericParams()
364 .Direction(numeric::Direction::increasing)
365 .Updates({{0, 1ms, 80.0},
366 {1, 2ms, 99.0},
367 {0, 3ms, 100.0},
368 {1, 4ms, 98.0}})
369 .Expected({{0, 3ms, 100.0}}),
370 NumericParams()
371 .Direction(numeric::Direction::decreasing)
372 .Updates({{0, 1ms, 100.0}, {0, 2ms, 91.0}})
373 .Expected({}),
374 NumericParams()
375 .Direction(numeric::Direction::decreasing)
376 .Updates({{0, 1ms, 100.0}, {0, 2ms, 80.0}})
377 .Expected({{0, 2ms, 80.0}}),
378 NumericParams()
379 .Direction(numeric::Direction::decreasing)
380 .Updates({{0, 1ms, 100.0},
381 {0, 2ms, 80.0},
382 {0, 3ms, 99.0},
383 {0, 4ms, 85.0}})
384 .Expected({{0, 4ms, 85.0}}),
385 NumericParams()
386 .Direction(numeric::Direction::decreasing)
387 .Updates({{0, 1ms, 100.0},
388 {0, 2ms, 80.0},
389 {1, 3ms, 99.0},
390 {1, 4ms, 88.0}})
391 .Expected({{0, 2ms, 80.0}, {1, 4ms, 88.0}}),
392 NumericParams()
393 .Direction(numeric::Direction::either)
394 .Updates({{0, 1ms, 98.0}, {0, 2ms, 91.0}})
395 .Expected({}),
396 NumericParams()
397 .Direction(numeric::Direction::either)
398 .Updates({{0, 1ms, 100.0},
399 {0, 2ms, 80.0},
400 {0, 3ms, 85.0},
401 {0, 4ms, 91.0}})
402 .Expected({{0, 4ms, 91.0}}),
403 NumericParams()
404 .Direction(numeric::Direction::either)
405 .Updates({{0, 1ms, 100.0},
406 {1, 2ms, 80.0},
407 {0, 3ms, 85.0},
408 {1, 4ms, 91.0}})
409 .Expected({{0, 3ms, 85.0},
410 {1, 4ms, 91.0}})));
Wludzik, Jozef1477fe62021-01-02 11:56:10 +0100411
412TEST_P(TestNumericThresholdWithDwellTime2,
413 senorsIsUpdatedMultipleTimesSleepAfterLastUpdate)
414{
415 InSequence seq;
416 for (const auto& [index, timestamp, value] : GetParam().expected)
417 {
418 EXPECT_CALL(actionMock, commit(sensorNames[index], timestamp, value));
419 }
420
421 sut->initialize();
422 for (const auto& [index, timestamp, value] : GetParam().updates)
423 {
424 sut->sensorUpdated(*sensorMocks[index], timestamp, value);
425 }
426 sleep();
427}