blob: 3dd2baa346cc2fa67858b81b18bbe932ee72162b [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
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +000026 std::shared_ptr<DiscreteThreshold> makeThreshold(Milliseconds dwellTime,
27 double thresholdValue)
Szymon Dompkef763c9e2021-03-12 09:19:22 +010028 {
29 std::vector<std::unique_ptr<interfaces::TriggerAction>> actions;
30 actions.push_back(std::move(actionMockPtr));
31
32 return std::make_shared<DiscreteThreshold>(
33 DbusEnvironment::getIoc(),
34 utils::convContainer<std::shared_ptr<interfaces::Sensor>>(
35 sensorMocks),
36 sensorNames, std::move(actions), dwellTime, thresholdValue,
37 "treshold_name");
38 }
39
40 void SetUp() override
41 {
42 sut = makeThreshold(0ms, 90.0);
43 }
44};
45
46TEST_F(TestDiscreteThreshold, initializeThresholdExpectAllSensorsAreRegistered)
47{
48 for (auto& sensor : sensorMocks)
49 {
50 EXPECT_CALL(*sensor,
51 registerForUpdates(Truly([sut = sut.get()](const auto& x) {
52 return x.lock().get() == sut;
53 })));
54 }
55
56 sut->initialize();
57}
58
59TEST_F(TestDiscreteThreshold, thresholdIsNotInitializeExpectNoActionCommit)
60{
61 EXPECT_CALL(actionMock, commit(_, _, _)).Times(0);
62}
63
64struct DiscreteParams
65{
66 struct UpdateParams
67 {
68 size_t sensor;
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +010069 Milliseconds timestamp;
Szymon Dompkef763c9e2021-03-12 09:19:22 +010070 double value;
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +000071 Milliseconds sleepAfter;
Szymon Dompkef763c9e2021-03-12 09:19:22 +010072
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +010073 UpdateParams(size_t sensor, Milliseconds timestamp, double value,
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +000074 Milliseconds sleepAfter = 0ms) :
Szymon Dompkef763c9e2021-03-12 09:19:22 +010075 sensor(sensor),
76 timestamp(timestamp), value(value), sleepAfter(sleepAfter)
77 {}
78 };
79
80 struct ExpectedParams
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 waitMin;
Szymon Dompkef763c9e2021-03-12 09:19:22 +010086
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +010087 ExpectedParams(size_t sensor, Milliseconds timestamp, double value,
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +000088 Milliseconds waitMin = 0ms) :
Szymon Dompkef763c9e2021-03-12 09:19:22 +010089 sensor(sensor),
90 timestamp(timestamp), value(value), waitMin(waitMin)
91 {}
92 };
93
94 DiscreteParams& Updates(std::vector<UpdateParams> val)
95 {
96 updates = std::move(val);
97 return *this;
98 }
99
100 DiscreteParams& Expected(std::vector<ExpectedParams> val)
101 {
102 expected = std::move(val);
103 return *this;
104 }
105
106 DiscreteParams& ThresholdValue(double val)
107 {
108 thresholdValue = val;
109 return *this;
110 }
111
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000112 DiscreteParams& DwellTime(Milliseconds val)
Szymon Dompkef763c9e2021-03-12 09:19:22 +0100113 {
114 dwellTime = std::move(val);
115 return *this;
116 }
117
118 friend void PrintTo(const DiscreteParams& o, std::ostream* os)
119 {
120 *os << "{ DwellTime: " << o.dwellTime.count() << "ms ";
121 *os << ", ThresholdValue: " << o.thresholdValue;
122 *os << ", Updates: ";
123 for (const auto& [index, timestamp, value, sleepAfter] : o.updates)
124 {
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100125 *os << "{ SensorIndex: " << index
126 << ", Timestamp: " << timestamp.count() << ", Value: " << value
Szymon Dompkef763c9e2021-03-12 09:19:22 +0100127 << ", SleepAfter: " << sleepAfter.count() << "ms }, ";
128 }
129 *os << "Expected: ";
130 for (const auto& [index, timestamp, value, waitMin] : o.expected)
131 {
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100132 *os << "{ SensorIndex: " << index
133 << ", Timestamp: " << timestamp.count() << ", Value: " << value
134 << ", waitMin: " << waitMin.count() << "ms }, ";
Szymon Dompkef763c9e2021-03-12 09:19:22 +0100135 }
136 *os << " }";
137 }
138
139 std::vector<UpdateParams> updates;
140 std::vector<ExpectedParams> expected;
141 double thresholdValue = 0.0;
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000142 Milliseconds dwellTime = 0ms;
Szymon Dompkef763c9e2021-03-12 09:19:22 +0100143};
144
145class TestDiscreteThresholdCommon :
146 public TestDiscreteThreshold,
147 public WithParamInterface<DiscreteParams>
148{
149 public:
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000150 void sleep(Milliseconds duration)
Szymon Dompkef763c9e2021-03-12 09:19:22 +0100151 {
152 if (duration != 0ms)
153 {
154 DbusEnvironment::sleepFor(duration);
155 }
156 }
157
158 void testBodySensorIsUpdatedMultipleTimes()
159 {
160 std::vector<std::chrono::time_point<std::chrono::high_resolution_clock>>
161 timestamps(sensorMocks.size());
162
163 sut->initialize();
164
165 InSequence seq;
166
167 for (const auto& [index, timestamp, value, waitMin] :
168 GetParam().expected)
169 {
170 EXPECT_CALL(actionMock,
171 commit(sensorNames[index], timestamp, value))
172 .WillOnce(DoAll(
173 InvokeWithoutArgs([idx = index, &timestamps] {
174 timestamps[idx] =
175 std::chrono::high_resolution_clock::now();
176 }),
177 InvokeWithoutArgs(DbusEnvironment::setPromise("commit"))));
178 }
179
180 auto start = std::chrono::high_resolution_clock::now();
181
182 for (const auto& [index, timestamp, value, sleepAfter] :
183 GetParam().updates)
184 {
185 sut->sensorUpdated(*sensorMocks[index], timestamp, value);
186 sleep(sleepAfter);
187 }
188
189 EXPECT_THAT(DbusEnvironment::waitForFutures("commit"), true);
190 for (const auto& [index, timestamp, value, waitMin] :
191 GetParam().expected)
192 {
193 EXPECT_THAT(timestamps[index] - start, Ge(waitMin));
194 }
195 }
196};
197
198class TestDiscreteThresholdNoDwellTime : public TestDiscreteThresholdCommon
199{
200 public:
201 void SetUp() override
202 {
203 sut = makeThreshold(0ms, GetParam().thresholdValue);
204 }
205};
206
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100207INSTANTIATE_TEST_SUITE_P(_, TestDiscreteThresholdNoDwellTime,
208 Values(DiscreteParams()
209 .ThresholdValue(90.0)
210 .Updates({{0, 1ms, 80.0}, {0, 2ms, 89.0}})
211 .Expected({}),
212 DiscreteParams()
213 .ThresholdValue(90.0)
214 .Updates({{0, 1ms, 80.0},
215 {0, 2ms, 90.0},
216 {0, 3ms, 80.0},
217 {0, 4ms, 90.0}})
218 .Expected({{0, 2ms, 90.0}, {0, 4ms, 90.0}}),
219 DiscreteParams()
220 .ThresholdValue(90.0)
221 .Updates({{0, 1ms, 90.0},
222 {0, 2ms, 99.0},
223 {1, 3ms, 100.0},
224 {1, 4ms, 90.0}})
225 .Expected({{0, 1ms, 90.0},
226 {1, 4ms, 90.0}})));
Szymon Dompkef763c9e2021-03-12 09:19:22 +0100227
228TEST_P(TestDiscreteThresholdNoDwellTime, senorsIsUpdatedMultipleTimes)
229{
230 testBodySensorIsUpdatedMultipleTimes();
231}
232
233class TestDiscreteThresholdWithDwellTime : public TestDiscreteThresholdCommon
234{
235 public:
236 void SetUp() override
237 {
238 sut = makeThreshold(GetParam().dwellTime, GetParam().thresholdValue);
239 }
240};
241
242INSTANTIATE_TEST_SUITE_P(
243 _, TestDiscreteThresholdWithDwellTime,
244 Values(DiscreteParams()
245 .DwellTime(200ms)
246 .ThresholdValue(90.0)
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100247 .Updates({{0, 1ms, 90.0, 100ms}, {0, 2ms, 91.0}, {0, 3ms, 90.0}})
248 .Expected({{0, 3ms, 90.0, 300ms}}),
Szymon Dompkef763c9e2021-03-12 09:19:22 +0100249 DiscreteParams()
250 .DwellTime(100ms)
251 .ThresholdValue(90.0)
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100252 .Updates({{0, 1ms, 90.0, 100ms}})
253 .Expected({{0, 1ms, 90.0, 100ms}}),
Szymon Dompkef763c9e2021-03-12 09:19:22 +0100254 DiscreteParams()
255 .DwellTime(1000ms)
256 .ThresholdValue(90.0)
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100257 .Updates({{0, 1ms, 90.0, 700ms},
258 {0, 1ms, 91.0, 100ms},
259 {0, 1ms, 90.0, 300ms},
260 {0, 1ms, 91.0, 100ms}})
Szymon Dompkef763c9e2021-03-12 09:19:22 +0100261 .Expected({}),
262 DiscreteParams()
263 .DwellTime(200ms)
264 .ThresholdValue(90.0)
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100265 .Updates({{0, 1ms, 90.0},
266 {1, 2ms, 89.0, 100ms},
267 {1, 3ms, 90.0, 100ms},
268 {1, 4ms, 89.0, 100ms},
269 {1, 5ms, 90.0, 300ms},
270 {1, 6ms, 89.0, 100ms}})
271 .Expected({{0, 1ms, 90, 200ms}, {1, 5ms, 90, 500ms}})));
Szymon Dompkef763c9e2021-03-12 09:19:22 +0100272
273TEST_P(TestDiscreteThresholdWithDwellTime, senorsIsUpdatedMultipleTimes)
274{
275 testBodySensorIsUpdatedMultipleTimes();
276}