blob: ebd50cc24e2f846eeaf61520086f1d942bb0945d [file] [log] [blame]
Szymon Dompkef763c9e2021-03-12 09:19:22 +01001#include "dbus_environment.hpp"
2#include "discrete_threshold.hpp"
3#include "helpers.hpp"
4#include "mocks/sensor_mock.hpp"
5#include "mocks/trigger_action_mock.hpp"
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +01006#include "types/duration_types.hpp"
Szymon Dompkef763c9e2021-03-12 09:19:22 +01007#include "utils/conv_container.hpp"
8
9#include <gmock/gmock.h>
10
11using namespace testing;
12using namespace std::chrono_literals;
13
14class TestDiscreteThreshold : public Test
15{
16 public:
17 std::vector<std::shared_ptr<SensorMock>> sensorMocks = {
18 std::make_shared<NiceMock<SensorMock>>(),
19 std::make_shared<NiceMock<SensorMock>>()};
20 std::vector<std::string> sensorNames = {"Sensor1", "Sensor2"};
21 std::unique_ptr<TriggerActionMock> actionMockPtr =
22 std::make_unique<StrictMock<TriggerActionMock>>();
23 TriggerActionMock& actionMock = *actionMockPtr;
24 std::shared_ptr<DiscreteThreshold> sut;
25
Szymon Dompke94f71c52021-12-10 07:16:33 +010026 std::shared_ptr<DiscreteThreshold>
27 makeThreshold(Milliseconds dwellTime, double thresholdValue,
28 discrete::Severity severity = discrete::Severity::ok)
Szymon Dompkef763c9e2021-03-12 09:19:22 +010029 {
30 std::vector<std::unique_ptr<interfaces::TriggerAction>> actions;
31 actions.push_back(std::move(actionMockPtr));
32
33 return std::make_shared<DiscreteThreshold>(
34 DbusEnvironment::getIoc(),
35 utils::convContainer<std::shared_ptr<interfaces::Sensor>>(
36 sensorMocks),
Szymon Dompke94f71c52021-12-10 07:16:33 +010037 std::move(actions), dwellTime, thresholdValue, "treshold name",
38 severity);
Szymon Dompkef763c9e2021-03-12 09:19:22 +010039 }
40
41 void SetUp() override
42 {
Szymon Dompke94f71c52021-12-10 07:16:33 +010043 for (size_t idx = 0; idx < sensorMocks.size(); idx++)
44 {
45 ON_CALL(*sensorMocks.at(idx), getName())
46 .WillByDefault(Return(sensorNames[idx]));
47 }
48
49 sut = makeThreshold(0ms, 90.0, discrete::Severity::critical);
Szymon Dompkef763c9e2021-03-12 09:19:22 +010050 }
51};
52
53TEST_F(TestDiscreteThreshold, initializeThresholdExpectAllSensorsAreRegistered)
54{
55 for (auto& sensor : sensorMocks)
56 {
57 EXPECT_CALL(*sensor,
58 registerForUpdates(Truly([sut = sut.get()](const auto& x) {
59 return x.lock().get() == sut;
60 })));
61 }
62
63 sut->initialize();
64}
65
66TEST_F(TestDiscreteThreshold, thresholdIsNotInitializeExpectNoActionCommit)
67{
68 EXPECT_CALL(actionMock, commit(_, _, _)).Times(0);
69}
70
Szymon Dompke94f71c52021-12-10 07:16:33 +010071TEST_F(TestDiscreteThreshold, getLabeledParamsReturnsCorrectly)
72{
73 LabeledThresholdParam expected = discrete::LabeledThresholdParam(
74 "treshold name", discrete::Severity::critical, 0, std::to_string(90.0));
75 EXPECT_EQ(sut->getThresholdParam(), expected);
76}
77
Szymon Dompkef763c9e2021-03-12 09:19:22 +010078struct DiscreteParams
79{
80 struct UpdateParams
81 {
82 size_t sensor;
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +010083 Milliseconds timestamp;
Szymon Dompkef763c9e2021-03-12 09:19:22 +010084 double value;
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +000085 Milliseconds sleepAfter;
Szymon Dompkef763c9e2021-03-12 09:19:22 +010086
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +010087 UpdateParams(size_t sensor, Milliseconds timestamp, double value,
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +000088 Milliseconds sleepAfter = 0ms) :
Szymon Dompkef763c9e2021-03-12 09:19:22 +010089 sensor(sensor),
90 timestamp(timestamp), value(value), sleepAfter(sleepAfter)
91 {}
92 };
93
94 struct ExpectedParams
95 {
96 size_t sensor;
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +010097 Milliseconds timestamp;
Szymon Dompkef763c9e2021-03-12 09:19:22 +010098 double value;
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +000099 Milliseconds waitMin;
Szymon Dompkef763c9e2021-03-12 09:19:22 +0100100
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100101 ExpectedParams(size_t sensor, Milliseconds timestamp, double value,
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000102 Milliseconds waitMin = 0ms) :
Szymon Dompkef763c9e2021-03-12 09:19:22 +0100103 sensor(sensor),
104 timestamp(timestamp), value(value), waitMin(waitMin)
105 {}
106 };
107
108 DiscreteParams& Updates(std::vector<UpdateParams> val)
109 {
110 updates = std::move(val);
111 return *this;
112 }
113
114 DiscreteParams& Expected(std::vector<ExpectedParams> val)
115 {
116 expected = std::move(val);
117 return *this;
118 }
119
120 DiscreteParams& ThresholdValue(double val)
121 {
122 thresholdValue = val;
123 return *this;
124 }
125
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000126 DiscreteParams& DwellTime(Milliseconds val)
Szymon Dompkef763c9e2021-03-12 09:19:22 +0100127 {
128 dwellTime = std::move(val);
129 return *this;
130 }
131
132 friend void PrintTo(const DiscreteParams& o, std::ostream* os)
133 {
134 *os << "{ DwellTime: " << o.dwellTime.count() << "ms ";
135 *os << ", ThresholdValue: " << o.thresholdValue;
136 *os << ", Updates: ";
137 for (const auto& [index, timestamp, value, sleepAfter] : o.updates)
138 {
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100139 *os << "{ SensorIndex: " << index
140 << ", Timestamp: " << timestamp.count() << ", Value: " << value
Szymon Dompkef763c9e2021-03-12 09:19:22 +0100141 << ", SleepAfter: " << sleepAfter.count() << "ms }, ";
142 }
143 *os << "Expected: ";
144 for (const auto& [index, timestamp, value, waitMin] : o.expected)
145 {
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100146 *os << "{ SensorIndex: " << index
147 << ", Timestamp: " << timestamp.count() << ", Value: " << value
148 << ", waitMin: " << waitMin.count() << "ms }, ";
Szymon Dompkef763c9e2021-03-12 09:19:22 +0100149 }
150 *os << " }";
151 }
152
153 std::vector<UpdateParams> updates;
154 std::vector<ExpectedParams> expected;
155 double thresholdValue = 0.0;
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000156 Milliseconds dwellTime = 0ms;
Szymon Dompkef763c9e2021-03-12 09:19:22 +0100157};
158
159class TestDiscreteThresholdCommon :
160 public TestDiscreteThreshold,
161 public WithParamInterface<DiscreteParams>
162{
163 public:
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000164 void sleep(Milliseconds duration)
Szymon Dompkef763c9e2021-03-12 09:19:22 +0100165 {
166 if (duration != 0ms)
167 {
168 DbusEnvironment::sleepFor(duration);
169 }
170 }
171
172 void testBodySensorIsUpdatedMultipleTimes()
173 {
174 std::vector<std::chrono::time_point<std::chrono::high_resolution_clock>>
175 timestamps(sensorMocks.size());
176
177 sut->initialize();
178
179 InSequence seq;
180
181 for (const auto& [index, timestamp, value, waitMin] :
182 GetParam().expected)
183 {
184 EXPECT_CALL(actionMock,
185 commit(sensorNames[index], timestamp, value))
186 .WillOnce(DoAll(
187 InvokeWithoutArgs([idx = index, &timestamps] {
188 timestamps[idx] =
189 std::chrono::high_resolution_clock::now();
190 }),
191 InvokeWithoutArgs(DbusEnvironment::setPromise("commit"))));
192 }
193
194 auto start = std::chrono::high_resolution_clock::now();
195
196 for (const auto& [index, timestamp, value, sleepAfter] :
197 GetParam().updates)
198 {
199 sut->sensorUpdated(*sensorMocks[index], timestamp, value);
200 sleep(sleepAfter);
201 }
202
203 EXPECT_THAT(DbusEnvironment::waitForFutures("commit"), true);
204 for (const auto& [index, timestamp, value, waitMin] :
205 GetParam().expected)
206 {
207 EXPECT_THAT(timestamps[index] - start, Ge(waitMin));
208 }
209 }
210};
211
212class TestDiscreteThresholdNoDwellTime : public TestDiscreteThresholdCommon
213{
214 public:
215 void SetUp() override
216 {
Szymon Dompke94f71c52021-12-10 07:16:33 +0100217
218 for (size_t idx = 0; idx < sensorMocks.size(); idx++)
219 {
220 ON_CALL(*sensorMocks.at(idx), getName())
221 .WillByDefault(Return(sensorNames[idx]));
222 }
223
Szymon Dompkef763c9e2021-03-12 09:19:22 +0100224 sut = makeThreshold(0ms, GetParam().thresholdValue);
225 }
226};
227
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100228INSTANTIATE_TEST_SUITE_P(_, TestDiscreteThresholdNoDwellTime,
229 Values(DiscreteParams()
230 .ThresholdValue(90.0)
231 .Updates({{0, 1ms, 80.0}, {0, 2ms, 89.0}})
232 .Expected({}),
233 DiscreteParams()
234 .ThresholdValue(90.0)
235 .Updates({{0, 1ms, 80.0},
236 {0, 2ms, 90.0},
237 {0, 3ms, 80.0},
238 {0, 4ms, 90.0}})
239 .Expected({{0, 2ms, 90.0}, {0, 4ms, 90.0}}),
240 DiscreteParams()
241 .ThresholdValue(90.0)
242 .Updates({{0, 1ms, 90.0},
243 {0, 2ms, 99.0},
244 {1, 3ms, 100.0},
245 {1, 4ms, 90.0}})
246 .Expected({{0, 1ms, 90.0},
247 {1, 4ms, 90.0}})));
Szymon Dompkef763c9e2021-03-12 09:19:22 +0100248
249TEST_P(TestDiscreteThresholdNoDwellTime, senorsIsUpdatedMultipleTimes)
250{
251 testBodySensorIsUpdatedMultipleTimes();
252}
253
254class TestDiscreteThresholdWithDwellTime : public TestDiscreteThresholdCommon
255{
256 public:
257 void SetUp() override
258 {
Szymon Dompke94f71c52021-12-10 07:16:33 +0100259 for (size_t idx = 0; idx < sensorMocks.size(); idx++)
260 {
261 ON_CALL(*sensorMocks.at(idx), getName())
262 .WillByDefault(Return(sensorNames[idx]));
263 }
264
Szymon Dompkef763c9e2021-03-12 09:19:22 +0100265 sut = makeThreshold(GetParam().dwellTime, GetParam().thresholdValue);
266 }
267};
268
269INSTANTIATE_TEST_SUITE_P(
270 _, TestDiscreteThresholdWithDwellTime,
271 Values(DiscreteParams()
272 .DwellTime(200ms)
273 .ThresholdValue(90.0)
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100274 .Updates({{0, 1ms, 90.0, 100ms}, {0, 2ms, 91.0}, {0, 3ms, 90.0}})
275 .Expected({{0, 3ms, 90.0, 300ms}}),
Szymon Dompkef763c9e2021-03-12 09:19:22 +0100276 DiscreteParams()
277 .DwellTime(100ms)
278 .ThresholdValue(90.0)
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100279 .Updates({{0, 1ms, 90.0, 100ms}})
280 .Expected({{0, 1ms, 90.0, 100ms}}),
Szymon Dompkef763c9e2021-03-12 09:19:22 +0100281 DiscreteParams()
282 .DwellTime(1000ms)
283 .ThresholdValue(90.0)
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100284 .Updates({{0, 1ms, 90.0, 700ms},
285 {0, 1ms, 91.0, 100ms},
286 {0, 1ms, 90.0, 300ms},
287 {0, 1ms, 91.0, 100ms}})
Szymon Dompkef763c9e2021-03-12 09:19:22 +0100288 .Expected({}),
289 DiscreteParams()
290 .DwellTime(200ms)
291 .ThresholdValue(90.0)
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100292 .Updates({{0, 1ms, 90.0},
293 {1, 2ms, 89.0, 100ms},
294 {1, 3ms, 90.0, 100ms},
295 {1, 4ms, 89.0, 100ms},
296 {1, 5ms, 90.0, 300ms},
297 {1, 6ms, 89.0, 100ms}})
298 .Expected({{0, 1ms, 90, 200ms}, {1, 5ms, 90, 500ms}})));
Szymon Dompkef763c9e2021-03-12 09:19:22 +0100299
300TEST_P(TestDiscreteThresholdWithDwellTime, senorsIsUpdatedMultipleTimes)
301{
302 testBodySensorIsUpdatedMultipleTimes();
303}