blob: cd6a6ecd2650284228f7d9f4e71989fab69b444f [file] [log] [blame]
Krzysztof Grobelny80697712021-03-04 09:49:27 +00001#include "fakes/clock_fake.hpp"
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +00002#include "helpers.hpp"
Krzysztof Grobelnyc8e3a642020-10-23 12:29:16 +02003#include "metric.hpp"
Krzysztof Grobelnyf7ea2992022-01-27 11:04:58 +01004#include "mocks/metric_listener_mock.hpp"
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +01005#include "mocks/sensor_mock.hpp"
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +00006#include "params/metric_params.hpp"
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +01007#include "utils/conv_container.hpp"
Krzysztof Grobelnye8fc5752021-02-05 14:30:45 +00008#include "utils/conversion.hpp"
9#include "utils/tstring.hpp"
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +010010
11#include <gmock/gmock.h>
12
13using namespace testing;
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +000014using namespace std::chrono_literals;
15
Krzysztof Grobelnye8fc5752021-02-05 14:30:45 +000016namespace tstring = utils::tstring;
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +010017
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +010018constexpr Milliseconds systemTimestamp = 42ms;
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +010019
20class TestMetric : public Test
21{
22 public:
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +010023 TestMetric()
24 {
25 clockFake.steady.reset();
26 clockFake.system.set(systemTimestamp);
27 }
28
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +000029 static std::vector<std::shared_ptr<SensorMock>>
30 makeSensorMocks(size_t amount)
31 {
32 std::vector<std::shared_ptr<SensorMock>> result;
33 for (size_t i = 0; i < amount; ++i)
34 {
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +010035 auto& metricMock =
36 result.emplace_back(std::make_shared<NiceMock<SensorMock>>());
Krzysztof Grobelny9e8da542022-02-17 10:40:16 +010037 ON_CALL(*metricMock, metadata())
38 .WillByDefault(Return("metadata" + std::to_string(i)));
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +000039 }
40 return result;
41 }
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +010042
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +000043 std::shared_ptr<Metric> makeSut(const MetricParams& p)
44 {
45 return std::make_shared<Metric>(
46 utils::convContainer<std::shared_ptr<interfaces::Sensor>>(
47 sensorMocks),
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +010048 p.operationType(), p.id(), p.collectionTimeScope(),
Krzysztof Grobelny80697712021-03-04 09:49:27 +000049 p.collectionDuration(), std::move(clockFakePtr));
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +000050 }
51
Krzysztof Grobelny80697712021-03-04 09:49:27 +000052 MetricParams params = MetricParams()
53 .id("id")
Krzysztof Grobelny80697712021-03-04 09:49:27 +000054 .operationType(OperationType::avg)
55 .collectionTimeScope(CollectionTimeScope::point)
56 .collectionDuration(CollectionDuration(0ms));
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +000057 std::vector<std::shared_ptr<SensorMock>> sensorMocks = makeSensorMocks(1u);
Krzysztof Grobelny80697712021-03-04 09:49:27 +000058 std::unique_ptr<ClockFake> clockFakePtr = std::make_unique<ClockFake>();
59 ClockFake& clockFake = *clockFakePtr;
Krzysztof Grobelnyf7ea2992022-01-27 11:04:58 +010060 NiceMock<MetricListenerMock> listenerMock;
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +000061 std::shared_ptr<Metric> sut;
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +010062};
63
64TEST_F(TestMetric, subscribesForSensorDuringInitialization)
65{
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +000066 sut = makeSut(params);
67
68 EXPECT_CALL(*sensorMocks.front(),
Krzysztof Grobelnye8fc5752021-02-05 14:30:45 +000069 registerForUpdates(Truly([sut = sut.get()](const auto& a0) {
70 return a0.lock().get() == sut;
71 })));
72
73 sut->initialize();
74}
75
Lukasz Kazmierczak7e098e92021-09-16 15:59:56 +020076TEST_F(TestMetric, unsubscribesForSensorDuringDeinitialization)
77{
78 sut = makeSut(params);
79
80 EXPECT_CALL(*sensorMocks.front(),
81 unregisterFromUpdates(Truly([sut = sut.get()](const auto& a0) {
82 return a0.lock().get() == sut;
83 })));
84
85 sut->deinitialize();
86}
87
Krzysztof Grobelnye8fc5752021-02-05 14:30:45 +000088TEST_F(TestMetric, containsEmptyReadingAfterCreated)
89{
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +000090 sut = makeSut(params);
91
Krzysztof Grobelny9e8da542022-02-17 10:40:16 +010092 ASSERT_THAT(sut->getUpdatedReadings(), ElementsAre());
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +000093}
94
Krzysztof Grobelnyf7ea2992022-01-27 11:04:58 +010095TEST_F(TestMetric,
96 notifiesRegisteredListenersOnManualUpdateWhenMetricValueChanges)
97{
98 sut = makeSut(params.collectionTimeScope(CollectionTimeScope::startup));
99 sut->sensorUpdated(*sensorMocks.front(), Milliseconds{18}, 31.2);
100 sut->registerForUpdates(listenerMock);
101
102 EXPECT_CALL(listenerMock, metricUpdated()).Times(2);
103
104 sut->updateReadings(Milliseconds{50u});
105 sut->updateReadings(Milliseconds{100u});
106}
107
108TEST_F(TestMetric,
109 doesntNotifyRegisteredListenersOnManualUpdateWhenMetricValueDoesntChange)
110{
111 sut = makeSut(params.collectionTimeScope(CollectionTimeScope::startup)
112 .operationType(OperationType::max));
113 sut->sensorUpdated(*sensorMocks.front(), Milliseconds{18}, 31.2);
114 sut->registerForUpdates(listenerMock);
115
116 EXPECT_CALL(listenerMock, metricUpdated()).Times(0);
117
118 sut->updateReadings(Milliseconds{50u});
119 sut->sensorUpdated(*sensorMocks.front(), Milliseconds{180}, 11.);
120 sut->updateReadings(Milliseconds{100u});
121}
122
Krzysztof Grobelnye8fc5752021-02-05 14:30:45 +0000123class TestMetricAfterInitialization : public TestMetric
124{
125 public:
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000126 void SetUp() override
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +0100127 {
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000128 sut = makeSut(params);
Krzysztof Grobelnye8fc5752021-02-05 14:30:45 +0000129 sut->initialize();
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +0100130 }
Krzysztof Grobelnye8fc5752021-02-05 14:30:45 +0000131};
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +0100132
Krzysztof Grobelnye8fc5752021-02-05 14:30:45 +0000133TEST_F(TestMetricAfterInitialization, containsEmptyReading)
134{
Krzysztof Grobelny9e8da542022-02-17 10:40:16 +0100135 ASSERT_THAT(sut->getUpdatedReadings(), ElementsAre());
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +0100136}
137
Krzysztof Grobelnye8fc5752021-02-05 14:30:45 +0000138TEST_F(TestMetricAfterInitialization, updatesMetricValuesOnSensorUpdate)
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +0100139{
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100140 sut->sensorUpdated(*sensorMocks.front(), Milliseconds{18}, 31.2);
Krzysztof Grobelnye8fc5752021-02-05 14:30:45 +0000141
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100142 ASSERT_THAT(
Krzysztof Grobelny9e8da542022-02-17 10:40:16 +0100143 sut->getUpdatedReadings(),
144 ElementsAre(MetricValue{"id", "metadata0", 31.2,
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100145 std::chrono::duration_cast<Milliseconds>(
146 clockFake.system.timestamp())
147 .count()}));
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +0100148}
149
Krzysztof Grobelnye8fc5752021-02-05 14:30:45 +0000150TEST_F(TestMetricAfterInitialization,
151 throwsWhenUpdateIsPerformedOnUnknownSensor)
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +0100152{
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +0100153 auto sensor = std::make_shared<StrictMock<SensorMock>>();
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100154 EXPECT_THROW(sut->sensorUpdated(*sensor, Milliseconds{10}, 20.0),
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +0100155 std::out_of_range);
156}
157
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000158TEST_F(TestMetricAfterInitialization, dumpsConfiguration)
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +0100159{
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000160 namespace ts = utils::tstring;
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +0000161
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000162 ON_CALL(*sensorMocks.front(), id())
Krzysztof Grobelnye8fc5752021-02-05 14:30:45 +0000163 .WillByDefault(Return(SensorMock::makeId("service1", "path1")));
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +0100164 ON_CALL(*sensorMocks.front(), metadata())
165 .WillByDefault(Return("metadata1"));
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +0100166
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +0000167 const auto conf = sut->dumpConfiguration();
168
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000169 LabeledMetricParameters expected = {};
Krzysztof Grobelny80697712021-03-04 09:49:27 +0000170 expected.at_label<ts::Id>() = params.id();
Krzysztof Grobelny80697712021-03-04 09:49:27 +0000171 expected.at_label<ts::OperationType>() = params.operationType();
172 expected.at_label<ts::CollectionTimeScope>() = params.collectionTimeScope();
173 expected.at_label<ts::CollectionDuration>() = params.collectionDuration();
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000174 expected.at_label<ts::SensorPath>() = {
Szymon Dompke94f71c52021-12-10 07:16:33 +0100175 LabeledSensorInfo("service1", "path1", "metadata1")};
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000176
177 EXPECT_THAT(conf, Eq(expected));
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +0100178}
Krzysztof Grobelny80697712021-03-04 09:49:27 +0000179
Krzysztof Grobelnyf7ea2992022-01-27 11:04:58 +0100180TEST_F(TestMetricAfterInitialization, notifiesRegisteredListeners)
181{
182 EXPECT_CALL(listenerMock, metricUpdated());
183
184 sut->registerForUpdates(listenerMock);
185 sut->sensorUpdated(*sensorMocks.front(), Milliseconds{18}, 31.2);
186}
187
188TEST_F(TestMetricAfterInitialization,
189 doesntNotifyRegisteredListenersWhenValueDoesntChange)
190{
191 EXPECT_CALL(listenerMock, metricUpdated());
192
193 sut->registerForUpdates(listenerMock);
194 sut->sensorUpdated(*sensorMocks.front(), Milliseconds{18}, 31.2);
195 sut->sensorUpdated(*sensorMocks.front(), Milliseconds{70}, 31.2);
196}
197
198TEST_F(TestMetricAfterInitialization, doesntNotifyAfterUnRegisterListener)
199{
200 EXPECT_CALL(listenerMock, metricUpdated()).Times(0);
201
202 sut->registerForUpdates(listenerMock);
203 sut->unregisterFromUpdates(listenerMock);
204 sut->sensorUpdated(*sensorMocks.front(), Milliseconds{18}, 31.2);
205}
206
Krzysztof Grobelny80697712021-03-04 09:49:27 +0000207class TestMetricCalculationFunctions :
208 public TestMetric,
209 public WithParamInterface<MetricParams>
210{
211 public:
212 void SetUp() override
213 {
Krzysztof Grobelny80697712021-03-04 09:49:27 +0000214 sut = makeSut(params.operationType(GetParam().operationType())
215 .collectionTimeScope(GetParam().collectionTimeScope())
216 .collectionDuration(GetParam().collectionDuration()));
217 }
218
219 static std::vector<std::pair<Milliseconds, double>> defaultReadings()
220 {
221 std::vector<std::pair<Milliseconds, double>> ret;
222 ret.emplace_back(0ms, std::numeric_limits<double>::quiet_NaN());
223 ret.emplace_back(10ms, 14.);
224 ret.emplace_back(1ms, 3.);
225 ret.emplace_back(5ms, 7.);
226 return ret;
227 }
228};
229
Krzysztof Grobelny60fee072022-01-13 16:25:04 +0100230MetricParams defaultCollectionFunctionParams()
Krzysztof Grobelny80697712021-03-04 09:49:27 +0000231{
232 return MetricParams()
Krzysztof Grobelny80697712021-03-04 09:49:27 +0000233 .readings(TestMetricCalculationFunctions::defaultReadings())
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100234 .expectedReading(systemTimestamp + 16ms, 7.0);
Krzysztof Grobelny80697712021-03-04 09:49:27 +0000235}
236
Krzysztof Grobelny80697712021-03-04 09:49:27 +0000237MetricParams defaultPointParams()
238{
Krzysztof Grobelnyf7ea2992022-01-27 11:04:58 +0100239 return defaultCollectionFunctionParams()
240 .collectionTimeScope(CollectionTimeScope::point)
241 .expectedIsTimerRequired(false);
Krzysztof Grobelny80697712021-03-04 09:49:27 +0000242}
243
244INSTANTIATE_TEST_SUITE_P(
245 TimeScopePointReturnsLastReading, TestMetricCalculationFunctions,
Krzysztof Grobelny60fee072022-01-13 16:25:04 +0100246 Values(defaultPointParams().operationType(OperationType::min),
Krzysztof Grobelny80697712021-03-04 09:49:27 +0000247 defaultPointParams().operationType(OperationType::max),
248 defaultPointParams().operationType(OperationType::sum),
249 defaultPointParams().operationType(OperationType::avg)));
250
251MetricParams defaultMinParams()
252{
Krzysztof Grobelny60fee072022-01-13 16:25:04 +0100253 return defaultCollectionFunctionParams().operationType(OperationType::min);
Krzysztof Grobelny80697712021-03-04 09:49:27 +0000254}
255
256INSTANTIATE_TEST_SUITE_P(
257 ReturnsMinForGivenTimeScope, TestMetricCalculationFunctions,
258 Values(defaultMinParams()
259 .collectionTimeScope(CollectionTimeScope::interval)
260 .collectionDuration(CollectionDuration(100ms))
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100261 .expectedReading(systemTimestamp + 16ms, 3.0),
Krzysztof Grobelny80697712021-03-04 09:49:27 +0000262 defaultMinParams()
263 .collectionTimeScope(CollectionTimeScope::interval)
264 .collectionDuration(CollectionDuration(3ms))
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100265 .expectedReading(systemTimestamp + 16ms, 7.0),
Krzysztof Grobelny80697712021-03-04 09:49:27 +0000266 defaultMinParams()
267 .collectionTimeScope(CollectionTimeScope::startup)
Krzysztof Grobelnyf7ea2992022-01-27 11:04:58 +0100268 .expectedReading(systemTimestamp + 16ms, 3.0)
269 .expectedIsTimerRequired(false)));
Krzysztof Grobelny80697712021-03-04 09:49:27 +0000270
271MetricParams defaultMaxParams()
272{
Krzysztof Grobelny60fee072022-01-13 16:25:04 +0100273 return defaultCollectionFunctionParams().operationType(OperationType::max);
Krzysztof Grobelny80697712021-03-04 09:49:27 +0000274}
275
276INSTANTIATE_TEST_SUITE_P(
277 ReturnsMaxForGivenTimeScope, TestMetricCalculationFunctions,
278 Values(defaultMaxParams()
279 .collectionTimeScope(CollectionTimeScope::interval)
280 .collectionDuration(CollectionDuration(100ms))
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100281 .expectedReading(systemTimestamp + 16ms, 14.0),
Krzysztof Grobelny80697712021-03-04 09:49:27 +0000282 defaultMaxParams()
283 .collectionTimeScope(CollectionTimeScope::interval)
284 .collectionDuration(CollectionDuration(6ms))
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100285 .expectedReading(systemTimestamp + 16ms, 14.0),
Krzysztof Grobelny80697712021-03-04 09:49:27 +0000286 defaultMaxParams()
287 .collectionTimeScope(CollectionTimeScope::interval)
288 .collectionDuration(CollectionDuration(5ms))
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100289 .expectedReading(systemTimestamp + 16ms, 7.0),
Krzysztof Grobelny80697712021-03-04 09:49:27 +0000290 defaultMaxParams()
291 .collectionTimeScope(CollectionTimeScope::startup)
Krzysztof Grobelnyf7ea2992022-01-27 11:04:58 +0100292 .expectedReading(systemTimestamp + 16ms, 14.0)
293 .expectedIsTimerRequired(false)));
Krzysztof Grobelny80697712021-03-04 09:49:27 +0000294
295MetricParams defaultSumParams()
296{
Krzysztof Grobelny60fee072022-01-13 16:25:04 +0100297 return defaultCollectionFunctionParams().operationType(OperationType::sum);
Krzysztof Grobelny80697712021-03-04 09:49:27 +0000298}
299
300INSTANTIATE_TEST_SUITE_P(
301 ReturnsSumForGivenTimeScope, TestMetricCalculationFunctions,
302 Values(defaultSumParams()
303 .collectionTimeScope(CollectionTimeScope::interval)
304 .collectionDuration(CollectionDuration(100ms))
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100305 .expectedReading(systemTimestamp + 16ms,
306 14. * 0.01 + 3. * 0.001 + 7. * 0.005),
Krzysztof Grobelny80697712021-03-04 09:49:27 +0000307 defaultSumParams()
308 .collectionTimeScope(CollectionTimeScope::interval)
309 .collectionDuration(CollectionDuration(8ms))
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100310 .expectedReading(systemTimestamp + 16ms,
311 14. * 0.002 + 3. * 0.001 + 7 * 0.005),
Krzysztof Grobelny80697712021-03-04 09:49:27 +0000312 defaultSumParams()
313 .collectionTimeScope(CollectionTimeScope::interval)
314 .collectionDuration(CollectionDuration(6ms))
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100315 .expectedReading(systemTimestamp + 16ms, 3. * 0.001 + 7 * 0.005),
Krzysztof Grobelny80697712021-03-04 09:49:27 +0000316 defaultSumParams()
317 .collectionTimeScope(CollectionTimeScope::startup)
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100318 .expectedReading(systemTimestamp + 16ms,
319 14. * 0.01 + 3. * 0.001 + 7 * 0.005)));
Krzysztof Grobelny80697712021-03-04 09:49:27 +0000320
321MetricParams defaultAvgParams()
322{
Krzysztof Grobelny60fee072022-01-13 16:25:04 +0100323 return defaultCollectionFunctionParams().operationType(OperationType::avg);
Krzysztof Grobelny80697712021-03-04 09:49:27 +0000324}
325
326INSTANTIATE_TEST_SUITE_P(
327 ReturnsAvgForGivenTimeScope, TestMetricCalculationFunctions,
328 Values(defaultAvgParams()
329 .collectionTimeScope(CollectionTimeScope::interval)
330 .collectionDuration(CollectionDuration(100ms))
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100331 .expectedReading(systemTimestamp + 16ms,
332 (14. * 10 + 3. * 1 + 7 * 5) / 16.),
Krzysztof Grobelny80697712021-03-04 09:49:27 +0000333 defaultAvgParams()
334 .collectionTimeScope(CollectionTimeScope::interval)
335 .collectionDuration(CollectionDuration(8ms))
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100336 .expectedReading(systemTimestamp + 16ms,
337 (14. * 2 + 3. * 1 + 7 * 5) / 8.),
Krzysztof Grobelny80697712021-03-04 09:49:27 +0000338 defaultAvgParams()
339 .collectionTimeScope(CollectionTimeScope::interval)
340 .collectionDuration(CollectionDuration(6ms))
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100341 .expectedReading(systemTimestamp + 16ms, (3. * 1 + 7 * 5) / 6.),
Krzysztof Grobelny80697712021-03-04 09:49:27 +0000342 defaultAvgParams()
343 .collectionTimeScope(CollectionTimeScope::startup)
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100344 .expectedReading(systemTimestamp + 16ms,
345 (14. * 10 + 3. * 1 + 7 * 5) / 16.)));
Krzysztof Grobelny80697712021-03-04 09:49:27 +0000346
347TEST_P(TestMetricCalculationFunctions, calculatesReadingValue)
348{
349 for (auto [timestamp, reading] : GetParam().readings())
350 {
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100351 sut->sensorUpdated(*sensorMocks.front(), clockFake.steadyTimestamp(),
Krzysztof Grobelny80697712021-03-04 09:49:27 +0000352 reading);
353 clockFake.advance(timestamp);
354 }
355
356 const auto [expectedTimestamp, expectedReading] =
357 GetParam().expectedReading();
Krzysztof Grobelny9e8da542022-02-17 10:40:16 +0100358 const auto readings = sut->getUpdatedReadings();
Krzysztof Grobelny80697712021-03-04 09:49:27 +0000359
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100360 EXPECT_THAT(readings,
Krzysztof Grobelny9e8da542022-02-17 10:40:16 +0100361 ElementsAre(MetricValue{"id", "metadata0", expectedReading,
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100362 expectedTimestamp.count()}));
Krzysztof Grobelny80697712021-03-04 09:49:27 +0000363}
364
365TEST_P(TestMetricCalculationFunctions,
366 calculatedReadingValueWithIntermediateCalculations)
367{
368 for (auto [timestamp, reading] : GetParam().readings())
369 {
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100370 sut->sensorUpdated(*sensorMocks.front(), clockFake.steadyTimestamp(),
Krzysztof Grobelny80697712021-03-04 09:49:27 +0000371 reading);
372 clockFake.advance(timestamp);
Krzysztof Grobelny9e8da542022-02-17 10:40:16 +0100373 sut->getUpdatedReadings();
Krzysztof Grobelny80697712021-03-04 09:49:27 +0000374 }
375
376 const auto [expectedTimestamp, expectedReading] =
377 GetParam().expectedReading();
Krzysztof Grobelny9e8da542022-02-17 10:40:16 +0100378 const auto readings = sut->getUpdatedReadings();
Krzysztof Grobelny80697712021-03-04 09:49:27 +0000379
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100380 EXPECT_THAT(readings,
Krzysztof Grobelny9e8da542022-02-17 10:40:16 +0100381 ElementsAre(MetricValue{"id", "metadata0", expectedReading,
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100382 expectedTimestamp.count()}));
Krzysztof Grobelny80697712021-03-04 09:49:27 +0000383}
Krzysztof Grobelnyf7ea2992022-01-27 11:04:58 +0100384
385TEST_P(TestMetricCalculationFunctions, returnsIsTimerRequired)
386{
387 EXPECT_THAT(sut->isTimerRequired(),
388 Eq(GetParam().expectedIsTimerRequired()));
389}
Krzysztof Grobelny9e8da542022-02-17 10:40:16 +0100390
391class TestMetricWithMultipleSensors : public TestMetric
392{
393 public:
394 TestMetricWithMultipleSensors()
395 {
396 sensorMocks = makeSensorMocks(7u);
397
398 sut = makeSut(params);
399 sut->initialize();
400 }
401};
402
403TEST_F(TestMetricWithMultipleSensors, readingsContainsAllReadingsInOrder)
404{
405 for (size_t i = 0; i < sensorMocks.size(); ++i)
406 {
407 sut->sensorUpdated(*sensorMocks[i], Milliseconds{i + 100}, i + 10.0);
408 sut->getUpdatedReadings();
409 }
410
411 clockFake.system.set(Milliseconds{72});
412
413 EXPECT_THAT(sut->getUpdatedReadings(),
414 ElementsAre(MetricValue{"id", "metadata0", 10.0, 72},
415 MetricValue{"id", "metadata1", 11.0, 72},
416 MetricValue{"id", "metadata2", 12.0, 72},
417 MetricValue{"id", "metadata3", 13.0, 72},
418 MetricValue{"id", "metadata4", 14.0, 72},
419 MetricValue{"id", "metadata5", 15.0, 72},
420 MetricValue{"id", "metadata6", 16.0, 72}));
421}
422
423TEST_F(TestMetricWithMultipleSensors, readingsContainOnlyAvailableSensors)
424{
425 for (auto i : {5u, 3u, 6u, 0u})
426 {
427 sut->sensorUpdated(*sensorMocks[i], Milliseconds{i + 100}, i + 10.0);
428 sut->getUpdatedReadings();
429 }
430
431 clockFake.system.set(Milliseconds{62});
432
433 EXPECT_THAT(sut->getUpdatedReadings(),
434 ElementsAre(MetricValue{"id", "metadata5", 15.0, 62},
435 MetricValue{"id", "metadata3", 13.0, 62},
436 MetricValue{"id", "metadata6", 16.0, 62},
437 MetricValue{"id", "metadata0", 10.0, 62}));
438}
439
440TEST_F(TestMetricWithMultipleSensors, readingsContainsAllReadingsOutOfOrder)
441{
442 for (auto i : {6u, 5u, 3u, 4u, 0u, 2u, 1u})
443 {
444 sut->sensorUpdated(*sensorMocks[i], Milliseconds{i + 100}, i + 10.0);
445 sut->getUpdatedReadings();
446 }
447
448 clockFake.system.set(Milliseconds{52});
449
450 EXPECT_THAT(sut->getUpdatedReadings(),
451 ElementsAre(MetricValue{"id", "metadata6", 16.0, 52},
452 MetricValue{"id", "metadata5", 15.0, 52},
453 MetricValue{"id", "metadata3", 13.0, 52},
454 MetricValue{"id", "metadata4", 14.0, 52},
455 MetricValue{"id", "metadata0", 10.0, 52},
456 MetricValue{"id", "metadata2", 12.0, 52},
457 MetricValue{"id", "metadata1", 11.0, 52}));
458}