xref: /openbmc/telemetry/tests/src/test_report.cpp (revision 39cc6ac9)
1 #include "dbus_environment.hpp"
2 #include "fakes/clock_fake.hpp"
3 #include "helpers.hpp"
4 #include "messages/collect_trigger_id.hpp"
5 #include "messages/trigger_presence_changed_ind.hpp"
6 #include "messages/update_report_ind.hpp"
7 #include "mocks/json_storage_mock.hpp"
8 #include "mocks/metric_mock.hpp"
9 #include "mocks/report_factory_mock.hpp"
10 #include "mocks/report_manager_mock.hpp"
11 #include "params/report_params.hpp"
12 #include "report.hpp"
13 #include "report_manager.hpp"
14 #include "utils/clock.hpp"
15 #include "utils/contains.hpp"
16 #include "utils/conv_container.hpp"
17 #include "utils/dbus_path_utils.hpp"
18 #include "utils/messanger.hpp"
19 #include "utils/string_utils.hpp"
20 #include "utils/transform.hpp"
21 #include "utils/tstring.hpp"
22 
23 #include <sdbusplus/exception.hpp>
24 
25 using namespace testing;
26 using namespace std::literals::string_literals;
27 using namespace std::chrono_literals;
28 using sdbusplus::message::object_path;
29 namespace tstring = utils::tstring;
30 
31 using ErrorMessageDbusType = std::tuple<std::string, std::string>;
32 using ErrorMessagesDbusType = std::vector<ErrorMessageDbusType>;
33 
34 constexpr Milliseconds systemTimestamp = 55ms;
35 
36 namespace
37 {
38 
39 ReportParams defaultParams()
40 {
41     return ReportParams();
42 }
43 
44 ReportParams defaultOnChangeParams()
45 {
46     return defaultParams().reportingType(ReportingType::onChange);
47 }
48 
49 } // namespace
50 
51 class TestReport : public Test
52 {
53   public:
54     std::unique_ptr<ReportManagerMock> reportManagerMock =
55         std::make_unique<NiceMock<ReportManagerMock>>();
56     std::unique_ptr<ReportFactoryMock> reportFactoryMock =
57         std::make_unique<NiceMock<ReportFactoryMock>>();
58     nlohmann::json storedConfiguration;
59     NiceMock<StorageMock> storageMock;
60     std::vector<std::shared_ptr<MetricMock>> metricMocks;
61     std::unique_ptr<ClockFake> clockFakePtr = std::make_unique<ClockFake>();
62     ClockFake& clockFake = *clockFakePtr;
63     std::unique_ptr<Report> sut;
64     utils::Messanger messanger;
65 
66     MockFunction<void()> checkPoint;
67 
68     TestReport() : messanger(DbusEnvironment::getIoc())
69     {
70         clockFake.system.set(systemTimestamp);
71         ON_CALL(storageMock, store(to_file_path(ReportParams().reportId()), _))
72             .WillByDefault(SaveArg<1>(&storedConfiguration));
73     }
74 
75     void initMetricMocks(
76         const std::vector<LabeledMetricParameters>& metricParameters)
77     {
78         for (auto i = metricMocks.size(); i < metricParameters.size(); ++i)
79         {
80             metricMocks.emplace_back(std::make_shared<NiceMock<MetricMock>>());
81         }
82         metricMocks.resize(metricParameters.size());
83 
84         std::vector<MetricValue> readings{{MetricValue{"a", "b", 17.1, 114},
85                                            MetricValue{"aa", "bb", 42.0, 74}}};
86         readings.resize(metricParameters.size());
87 
88         for (size_t i = 0; i < metricParameters.size(); ++i)
89         {
90             ON_CALL(*metricMocks[i], getUpdatedReadings())
91                 .WillByDefault(ReturnRefOfCopy(std::vector({readings[i]})));
92             ON_CALL(*metricMocks[i], dumpConfiguration())
93                 .WillByDefault(Return(metricParameters[i]));
94         }
95     }
96 
97     std::vector<std::shared_ptr<interfaces::Metric>>
98         getMetricsFromReadingParams(const ReadingParameters& params)
99     {
100         const auto metricParameters =
101             reportFactoryMock->convertMetricParams(params);
102         std::vector<std::shared_ptr<MetricMock>> metricMocks;
103 
104         for (size_t i = 0; i < metricParameters.size(); ++i)
105         {
106             metricMocks.emplace_back(std::make_shared<NiceMock<MetricMock>>());
107             ON_CALL(*metricMocks[i], dumpConfiguration())
108                 .WillByDefault(Return(metricParameters[i]));
109         }
110 
111         return utils::convContainer<std::shared_ptr<interfaces::Metric>>(
112             metricMocks);
113     }
114 
115     void SetUp() override
116     {
117         sut = makeReport(defaultParams());
118     }
119 
120     static interfaces::JsonStorage::FilePath to_file_path(std::string id)
121     {
122         return interfaces::JsonStorage::FilePath(
123             std::to_string(std::hash<std::string>{}(id)));
124     }
125 
126     std::unique_ptr<Report> makeReport(const ReportParams& params)
127     {
128         initMetricMocks(params.metricParameters());
129 
130         return std::make_unique<Report>(
131             DbusEnvironment::getIoc(), DbusEnvironment::getObjServer(),
132             params.reportId(), params.reportName(), params.reportingType(),
133             params.reportActions(), params.interval(), params.appendLimit(),
134             params.reportUpdates(), *reportManagerMock, storageMock,
135             utils::convContainer<std::shared_ptr<interfaces::Metric>>(
136                 metricMocks),
137             *reportFactoryMock, params.enabled(), std::move(clockFakePtr),
138             params.readings());
139     }
140 
141     template <class T>
142     static T getProperty(const std::string& path, const std::string& property)
143     {
144         return DbusEnvironment::getProperty<T>(path, Report::reportIfaceName,
145                                                property);
146     }
147 
148     template <class T>
149     static boost::system::error_code setProperty(const std::string& path,
150                                                  const std::string& property,
151                                                  const T& newValue)
152     {
153         return DbusEnvironment::setProperty<T>(path, Report::reportIfaceName,
154                                                property, newValue);
155     }
156 
157     template <class T>
158     struct ChangePropertyParams
159     {
160         Matcher<T> valueBefore = _;
161         T newValue;
162         Matcher<boost::system::error_code> ec =
163             Eq(boost::system::errc::success);
164         Matcher<T> valueAfter = Eq(newValue);
165     };
166 
167     template <class T>
168     static void changeProperty(const std::string& path,
169                                const std::string& property,
170                                ChangePropertyParams<T> p)
171     {
172         ASSERT_THAT(getProperty<T>(path, property), p.valueBefore);
173         ASSERT_THAT(setProperty<T>(path, property, p.newValue), p.ec);
174         EXPECT_THAT(getProperty<T>(path, property), p.valueAfter);
175     }
176 
177     boost::system::error_code call(const std::string& path,
178                                    const std::string& interface,
179                                    const std::string& method)
180     {
181         std::promise<boost::system::error_code> methodPromise;
182         DbusEnvironment::getBus()->async_method_call(
183             [&methodPromise](boost::system::error_code ec) {
184                 methodPromise.set_value(ec);
185             },
186             DbusEnvironment::serviceName(), path, interface, method);
187         return DbusEnvironment::waitForFuture(methodPromise.get_future());
188     }
189 
190     boost::system::error_code update(const std::string& path)
191     {
192         return call(path, Report::reportIfaceName, "Update");
193     }
194 
195     boost::system::error_code deleteReport(const std::string& path)
196     {
197         return call(path, Report::deleteIfaceName, "Delete");
198     }
199 
200     static std::pair<std::string, std::vector<std::string>>
201         makeStateDetail(const std::string& detailType,
202                         std::vector<std::string> detailArgs)
203     {
204         return make_pair(detailType, detailArgs);
205     }
206 };
207 
208 TEST_F(TestReport, returnsId)
209 {
210     EXPECT_THAT(sut->getId(), Eq(defaultParams().reportId()));
211 }
212 
213 TEST_F(TestReport, verifyIfPropertiesHaveValidValue)
214 {
215     EXPECT_THAT(getProperty<bool>(sut->getPath(), "Enabled"),
216                 Eq(defaultParams().enabled()));
217     EXPECT_THAT(getProperty<uint64_t>(sut->getPath(), "Interval"),
218                 Eq(defaultParams().interval().count()));
219     EXPECT_THAT(getProperty<bool>(sut->getPath(), "Persistency"), Eq(true));
220     EXPECT_THAT(
221         getProperty<std::vector<std::string>>(sut->getPath(), "ReportActions"),
222         Eq(utils::transform(defaultParams().reportActions(), [](const auto v) {
223             return utils::enumToString(v);
224         })));
225     EXPECT_THAT(getProperty<bool>(sut->getPath(), "EmitsReadingsUpdate"),
226                 Eq(utils::contains(defaultParams().reportActions(),
227                                    ReportAction::emitsReadingsUpdate)));
228     EXPECT_THAT(getProperty<uint64_t>(sut->getPath(), "AppendLimit"),
229                 Eq(defaultParams().appendLimit()));
230     EXPECT_THAT(getProperty<std::string>(sut->getPath(), "ReportingType"),
231                 Eq(utils::enumToString(defaultParams().reportingType())));
232     EXPECT_THAT(getProperty<std::string>(sut->getPath(), "ReportUpdates"),
233                 Eq(utils::enumToString(defaultParams().reportUpdates())));
234     EXPECT_THAT(
235         getProperty<bool>(sut->getPath(), "LogToMetricReportsCollection"),
236         Eq(utils::contains(defaultParams().reportActions(),
237                            ReportAction::logToMetricReportsCollection)));
238     EXPECT_THAT(getProperty<ReadingParameters>(
239                     sut->getPath(), "ReadingParametersFutureVersion"),
240                 Eq(toReadingParameters(defaultParams().metricParameters())));
241     EXPECT_THAT(getProperty<std::string>(sut->getPath(), "Name"),
242                 Eq(defaultParams().reportName()));
243     EXPECT_THAT(
244         getProperty<std::vector<object_path>>(sut->getPath(), "Triggers"),
245         IsEmpty());
246     EXPECT_THAT(
247         getProperty<ErrorMessagesDbusType>(sut->getPath(), "ErrorMessages"),
248         IsEmpty());
249 }
250 
251 TEST_F(TestReport, readingsAreInitialyEmpty)
252 {
253     EXPECT_THAT(getProperty<Readings>(sut->getPath(), "Readings"),
254                 Eq(Readings{}));
255 }
256 
257 TEST_F(TestReport, setReadingParametersWithNewParams)
258 {
259     ReadingParameters newParams = toReadingParameters(
260         std::vector<LabeledMetricParameters>{{LabeledMetricParameters{
261             {LabeledSensorInfo{"Service",
262                                "/xyz/openbmc_project/sensors/power/psu",
263                                "NewMetadata123"}},
264             OperationType::avg,
265             "NewMetricId123",
266             CollectionTimeScope::startup,
267             CollectionDuration(250ms)}}});
268     auto metrics = getMetricsFromReadingParams(newParams);
269 
270     EXPECT_CALL(*reportFactoryMock, updateMetrics(_, _, _))
271         .WillOnce(SetArgReferee<0>(metrics));
272     EXPECT_THAT(
273         setProperty(sut->getPath(), "ReadingParametersFutureVersion", newParams)
274             .value(),
275         Eq(boost::system::errc::success));
276     EXPECT_THAT(getProperty<ReadingParameters>(
277                     sut->getPath(), "ReadingParametersFutureVersion"),
278                 Eq(newParams));
279 }
280 
281 TEST_F(TestReport, setReadingParametersWithTooLongMetricId)
282 {
283     const ReadingParameters currentValue =
284         toReadingParameters(defaultParams().metricParameters());
285 
286     ReadingParameters newParams = toReadingParameters(
287         std::vector<LabeledMetricParameters>{{LabeledMetricParameters{
288             {LabeledSensorInfo{"Service",
289                                "/xyz/openbmc_project/sensors/power/psu",
290                                "NewMetadata123"}},
291             OperationType::avg,
292             utils::string_utils::getTooLongId(),
293             CollectionTimeScope::startup,
294             CollectionDuration(250ms)}}});
295 
296     changeProperty<ReadingParameters>(
297         sut->getPath(), "ReadingParametersFutureVersion",
298         {.valueBefore = Eq(currentValue),
299          .newValue = newParams,
300          .ec = Eq(boost::system::errc::invalid_argument),
301          .valueAfter = Eq(currentValue)});
302 }
303 
304 TEST_F(TestReport, setReportingTypeWithValidNewType)
305 {
306     changeProperty<std::string>(
307         sut->getPath(), "ReportingType",
308         {.valueBefore = Not(Eq(utils::enumToString(ReportingType::onRequest))),
309          .newValue = utils::enumToString(ReportingType::onRequest)});
310 }
311 
312 TEST_F(TestReport, setReportingTypeWithInvalidType)
313 {
314     const std::string currentValue =
315         utils::enumToString(defaultParams().reportingType());
316 
317     changeProperty<std::string>(
318         sut->getPath(), "ReportingType",
319         {.valueBefore = Eq(currentValue),
320          .newValue = "Periodic_ABC",
321          .ec = Eq(boost::system::errc::invalid_argument),
322          .valueAfter = Eq(currentValue)});
323 }
324 
325 TEST_F(TestReport, setReportActionsWithValidNewActions)
326 {
327     std::vector<std::string> newActions = {"EmitsReadingsUpdate"};
328     std::vector<std::string> currActions =
329         utils::transform(defaultParams().reportActions(),
330                          [](const auto v) { return utils::enumToString(v); });
331 
332     EXPECT_THAT(newActions, Ne(currActions));
333     EXPECT_THAT(
334         setProperty(sut->getPath(), "ReportActions", newActions).value(),
335         Eq(boost::system::errc::success));
336     EXPECT_THAT(
337         getProperty<std::vector<std::string>>(sut->getPath(), "ReportActions"),
338         UnorderedElementsAre("EmitsReadingsUpdate",
339                              "LogToMetricReportsCollection"));
340 }
341 
342 TEST_F(TestReport, setReportActionsWithValidUnsortedActions)
343 {
344     std::vector<std::string> newActions = {"LogToMetricReportsCollection",
345                                            "EmitsReadingsUpdate"};
346     std::vector<std::string> expectedActions = {"EmitsReadingsUpdate",
347                                                 "LogToMetricReportsCollection"};
348     std::vector<std::string> currActions =
349         utils::transform(defaultParams().reportActions(),
350                          [](const auto v) { return utils::enumToString(v); });
351 
352     EXPECT_THAT(newActions, Ne(currActions));
353     EXPECT_THAT(
354         setProperty(sut->getPath(), "ReportActions", newActions).value(),
355         Eq(boost::system::errc::success));
356     EXPECT_THAT(
357         getProperty<std::vector<std::string>>(sut->getPath(), "ReportActions"),
358         Eq(expectedActions));
359 }
360 
361 TEST_F(TestReport, setReportActionsWithEmptyActions)
362 {
363     std::vector<std::string> newActions = {};
364     std::vector<std::string> expectedActions = {"LogToMetricReportsCollection"};
365     std::vector<std::string> currActions =
366         utils::transform(defaultParams().reportActions(),
367                          [](const auto v) { return utils::enumToString(v); });
368 
369     EXPECT_THAT(newActions, Ne(currActions));
370     EXPECT_THAT(
371         setProperty(sut->getPath(), "ReportActions", newActions).value(),
372         Eq(boost::system::errc::success));
373     EXPECT_THAT(
374         getProperty<std::vector<std::string>>(sut->getPath(), "ReportActions"),
375         Eq(expectedActions));
376 }
377 
378 TEST_F(TestReport, setReportActionsWithInvalidActions)
379 {
380     std::vector<std::string> invalidActions = {"EmitsReadingsUpdate_1"};
381     EXPECT_THAT(
382         setProperty(sut->getPath(), "ReportActions", invalidActions).value(),
383         Eq(boost::system::errc::invalid_argument));
384     EXPECT_THAT(
385         getProperty<std::vector<std::string>>(sut->getPath(), "ReportActions"),
386         Eq(utils::transform(defaultParams().reportActions(), [](const auto v) {
387             return utils::enumToString(v);
388         })));
389 }
390 
391 TEST_F(TestReport, createReportWithEmptyActions)
392 {
393     std::vector<std::string> expectedActions = {"LogToMetricReportsCollection"};
394 
395     sut = makeReport(ReportParams().reportId("TestId_1").reportActions({}));
396     EXPECT_THAT(
397         getProperty<std::vector<std::string>>(sut->getPath(), "ReportActions"),
398         Eq(expectedActions));
399 }
400 
401 TEST_F(TestReport, createReportWithValidUnsortedActions)
402 {
403     std::vector<std::string> newActions = {"LogToMetricReportsCollection",
404                                            "EmitsReadingsUpdate"};
405     std::vector<std::string> expectedActions = {"EmitsReadingsUpdate",
406                                                 "LogToMetricReportsCollection"};
407 
408     sut = makeReport(
409         ReportParams()
410             .reportId("TestId_1")
411             .reportActions(utils::transform(newActions, [](const auto& action) {
412                 return utils::toReportAction(action);
413             })));
414     EXPECT_THAT(
415         getProperty<std::vector<std::string>>(sut->getPath(), "ReportActions"),
416         Eq(expectedActions));
417 }
418 
419 TEST_F(TestReport, setEnabledWithNewValue)
420 {
421     bool newValue = !defaultParams().enabled();
422     EXPECT_THAT(setProperty(sut->getPath(), "Enabled", newValue).value(),
423                 Eq(boost::system::errc::success));
424     EXPECT_THAT(getProperty<bool>(sut->getPath(), "Enabled"), Eq(newValue));
425 }
426 
427 TEST_F(TestReport, setIntervalWithValidValue)
428 {
429     uint64_t newValue = ReportManager::minInterval.count() * 42;
430     EXPECT_THAT(setProperty(sut->getPath(), "Interval", newValue).value(),
431                 Eq(boost::system::errc::success));
432     EXPECT_THAT(getProperty<uint64_t>(sut->getPath(), "Interval"),
433                 Eq(newValue));
434 }
435 
436 TEST_F(
437     TestReport,
438     settingIntervalWithInvalidValueDoesNotChangePropertyAndReturnsInvalidArgument)
439 {
440     uint64_t newValue = ReportManager::minInterval.count() - 1;
441     EXPECT_THAT(setProperty(sut->getPath(), "Interval", newValue).value(),
442                 Eq(boost::system::errc::invalid_argument));
443     EXPECT_THAT(getProperty<uint64_t>(sut->getPath(), "Interval"),
444                 Eq(defaultParams().interval().count()));
445 }
446 
447 TEST_F(TestReport, settingInvalidReportingTypeCreatesErrorMessage)
448 {
449     auto report = makeReport(defaultParams()
450                                  .reportId("report2")
451                                  .reportingType(ReportingType::onRequest)
452                                  .interval(Milliseconds{0}));
453 
454     EXPECT_THAT(
455         setProperty<std::string>(report->getPath(), "ReportingType", "Periodic")
456             .value(),
457         Eq(boost::system::errc::success));
458 
459     EXPECT_THAT(getProperty<std::string>(report->getPath(), "ReportingType"),
460                 Eq("Periodic"));
461     EXPECT_THAT(
462         getProperty<ErrorMessagesDbusType>(report->getPath(), "ErrorMessages"),
463         UnorderedElementsAre(
464             ErrorMessageDbusType(
465                 utils::enumToString(ErrorType::propertyConflict), "Interval"),
466             ErrorMessageDbusType(
467                 utils::enumToString(ErrorType::propertyConflict),
468                 "ReportingType")));
469 }
470 
471 TEST_F(TestReport, settingValidReportingTypeRemovesErrors)
472 {
473     auto report = makeReport(defaultParams()
474                                  .reportId("report2")
475                                  .reportingType(ReportingType::onRequest)
476                                  .interval(Milliseconds{0}));
477 
478     EXPECT_THAT(
479         setProperty<std::string>(report->getPath(), "ReportingType", "Periodic")
480             .value(),
481         Eq(boost::system::errc::success));
482     EXPECT_THAT(setProperty<std::string>(report->getPath(), "ReportingType",
483                                          "OnRequest")
484                     .value(),
485                 Eq(boost::system::errc::success));
486 
487     EXPECT_THAT(getProperty<std::string>(report->getPath(), "ReportingType"),
488                 Eq("OnRequest"));
489     EXPECT_THAT(
490         getProperty<ErrorMessagesDbusType>(report->getPath(), "ErrorMessages"),
491         IsEmpty());
492 }
493 
494 TEST_F(TestReport, settingInvalidIntervalDisablesReport)
495 {
496     auto report = makeReport(defaultParams()
497                                  .reportId("report2")
498                                  .reportingType(ReportingType::periodic)
499                                  .interval(ReportManager::minInterval));
500 
501     EXPECT_THAT(setProperty<uint64_t>(report->getPath(), "Interval", 0).value(),
502                 Eq(boost::system::errc::success));
503 
504     EXPECT_THAT(getProperty<uint64_t>(report->getPath(), "Interval"), Eq(0u));
505     EXPECT_THAT(
506         getProperty<ErrorMessagesDbusType>(report->getPath(), "ErrorMessages"),
507         UnorderedElementsAre(
508             ErrorMessageDbusType(
509                 utils::enumToString(ErrorType::propertyConflict), "Interval"),
510             ErrorMessageDbusType(
511                 utils::enumToString(ErrorType::propertyConflict),
512                 "ReportingType")));
513 }
514 
515 TEST_F(TestReport, settingValidIntervalEnablesReport)
516 {
517     auto report = makeReport(defaultParams()
518                                  .reportId("report2")
519                                  .reportingType(ReportingType::periodic)
520                                  .interval(ReportManager::minInterval));
521 
522     EXPECT_THAT(setProperty<uint64_t>(report->getPath(), "Interval", 0).value(),
523                 Eq(boost::system::errc::success));
524     EXPECT_THAT(setProperty<uint64_t>(report->getPath(), "Interval",
525                                       ReportManager::minInterval.count())
526                     .value(),
527                 Eq(boost::system::errc::success));
528 
529     EXPECT_THAT(getProperty<uint64_t>(report->getPath(), "Interval"),
530                 Eq(ReportManager::minInterval.count()));
531     EXPECT_THAT(
532         getProperty<ErrorMessagesDbusType>(report->getPath(), "ErrorMessages"),
533         IsEmpty());
534 }
535 
536 TEST_F(TestReport, settingEmitsReadingsUpdateHaveNoEffect)
537 {
538     EXPECT_THAT(
539         setProperty(sut->getPath(), "EmitsReadingsUpdate", true).value(),
540         Eq(boost::system::errc::read_only_file_system));
541     EXPECT_THAT(getProperty<bool>(sut->getPath(), "EmitsReadingsUpdate"),
542                 Eq(utils::contains(defaultParams().reportActions(),
543                                    ReportAction::emitsReadingsUpdate)));
544 }
545 
546 TEST_F(TestReport, settingLogToMetricReportCollectionHaveNoEffect)
547 {
548     EXPECT_THAT(
549         setProperty(sut->getPath(), "LogToMetricReportsCollection", true)
550             .value(),
551         Eq(boost::system::errc::read_only_file_system));
552     EXPECT_THAT(
553         getProperty<bool>(sut->getPath(), "LogToMetricReportsCollection"),
554         Eq(utils::contains(defaultParams().reportActions(),
555                            ReportAction::logToMetricReportsCollection)));
556 }
557 
558 TEST_F(TestReport, settingPersistencyToFalseRemovesReportFromStorage)
559 {
560     EXPECT_CALL(storageMock, store(_, _)).Times(0);
561     EXPECT_CALL(storageMock, remove(to_file_path(sut->getId())))
562         .Times(AtLeast(1));
563 
564     bool persistency = false;
565     EXPECT_THAT(setProperty(sut->getPath(), "Persistency", persistency).value(),
566                 Eq(boost::system::errc::success));
567     EXPECT_THAT(getProperty<bool>(sut->getPath(), "Persistency"),
568                 Eq(persistency));
569 }
570 
571 TEST_F(TestReport, deleteReport)
572 {
573     EXPECT_CALL(*reportManagerMock, removeReport(sut.get()));
574     auto ec = deleteReport(sut->getPath());
575     EXPECT_THAT(ec, Eq(boost::system::errc::success));
576 }
577 
578 TEST_F(TestReport, deletingNonExistingReportReturnInvalidRequestDescriptor)
579 {
580     auto ec =
581         deleteReport(utils::constants::reportDirPath.str + "NonExisting"s);
582     EXPECT_THAT(ec.value(), Eq(EBADR));
583 }
584 
585 TEST_F(TestReport, deleteReportExpectThatFileIsRemoveFromStorage)
586 {
587     EXPECT_CALL(storageMock, store(_, _)).Times(0);
588     EXPECT_CALL(storageMock, remove(to_file_path(sut->getId())))
589         .Times(AtLeast(1));
590 
591     auto ec = deleteReport(sut->getPath());
592     EXPECT_THAT(ec, Eq(boost::system::errc::success));
593 }
594 
595 TEST_F(TestReport, updatesTriggerIdWhenTriggerIsAdded)
596 {
597     utils::Messanger messanger(DbusEnvironment::getIoc());
598 
599     messanger.send(messages::TriggerPresenceChangedInd{
600         messages::Presence::Exist, "trigger1", {defaultParams().reportId()}});
601     messanger.send(messages::TriggerPresenceChangedInd{
602         messages::Presence::Exist, "trigger1", {defaultParams().reportId()}});
603     messanger.send(messages::TriggerPresenceChangedInd{
604         messages::Presence::Exist, "trigger2", {"someOtherReport"}});
605     messanger.send(messages::TriggerPresenceChangedInd{
606         messages::Presence::Exist,
607         "trigger3",
608         {"someOtherReport", defaultParams().reportId()}});
609 
610     EXPECT_THAT(
611         getProperty<std::vector<object_path>>(sut->getPath(), "Triggers"),
612         UnorderedElementsAre(utils::constants::triggerDirPath / "trigger1",
613                              utils::constants::triggerDirPath / "trigger3"));
614 }
615 
616 TEST_F(TestReport, updatesTriggerIdWhenTriggerIsRemoved)
617 {
618     utils::Messanger messanger(DbusEnvironment::getIoc());
619 
620     messanger.send(messages::TriggerPresenceChangedInd{
621         messages::Presence::Exist, "trigger1", {defaultParams().reportId()}});
622     messanger.send(messages::TriggerPresenceChangedInd{
623         messages::Presence::Exist, "trigger2", {defaultParams().reportId()}});
624     messanger.send(messages::TriggerPresenceChangedInd{
625         messages::Presence::Exist, "trigger3", {defaultParams().reportId()}});
626 
627     messanger.send(messages::TriggerPresenceChangedInd{
628         messages::Presence::Removed, "trigger1", {defaultParams().reportId()}});
629     messanger.send(messages::TriggerPresenceChangedInd{
630         messages::Presence::Removed, "trigger2", {}});
631     messanger.send(messages::TriggerPresenceChangedInd{
632         messages::Presence::Removed, "trigger1", {defaultParams().reportId()}});
633 
634     EXPECT_THAT(
635         getProperty<std::vector<object_path>>(sut->getPath(), "Triggers"),
636         UnorderedElementsAre(utils::constants::triggerDirPath / "trigger3"));
637 }
638 
639 TEST_F(TestReport, updatesTriggerIdWhenTriggerIsModified)
640 {
641     utils::Messanger messanger(DbusEnvironment::getIoc());
642 
643     messanger.send(messages::TriggerPresenceChangedInd{
644         messages::Presence::Exist, "trigger1", {defaultParams().reportId()}});
645     messanger.send(messages::TriggerPresenceChangedInd{
646         messages::Presence::Exist, "trigger2", {defaultParams().reportId()}});
647     messanger.send(messages::TriggerPresenceChangedInd{
648         messages::Presence::Exist, "trigger3", {defaultParams().reportId()}});
649 
650     messanger.send(messages::TriggerPresenceChangedInd{
651         messages::Presence::Exist, "trigger1", {defaultParams().reportId()}});
652     messanger.send(messages::TriggerPresenceChangedInd{
653         messages::Presence::Exist, "trigger2", {}});
654     messanger.send(messages::TriggerPresenceChangedInd{
655         messages::Presence::Exist, "trigger3", {defaultParams().reportId()}});
656 
657     EXPECT_THAT(
658         getProperty<std::vector<object_path>>(sut->getPath(), "Triggers"),
659         UnorderedElementsAre(utils::constants::triggerDirPath / "trigger1",
660                              utils::constants::triggerDirPath / "trigger3"));
661 }
662 
663 class TestReportStore :
664     public TestReport,
665     public WithParamInterface<std::pair<std::string, nlohmann::json>>
666 {
667     void SetUp() override
668     {}
669 };
670 
671 INSTANTIATE_TEST_SUITE_P(
672     _, TestReportStore,
673     Values(
674         std::make_pair("Enabled"s, nlohmann::json(defaultParams().enabled())),
675         std::make_pair("Version"s, nlohmann::json(6)),
676         std::make_pair("Id"s, nlohmann::json(defaultParams().reportId())),
677         std::make_pair("Name"s, nlohmann::json(defaultParams().reportName())),
678         std::make_pair("ReportingType",
679                        nlohmann::json(defaultParams().reportingType())),
680         std::make_pair("ReportActions", nlohmann::json(utils::transform(
681                                             defaultParams().reportActions(),
682                                             [](const auto v) {
683                                                 return utils::toUnderlying(v);
684                                             }))),
685         std::make_pair("Interval",
686                        nlohmann::json(defaultParams().interval().count())),
687         std::make_pair("AppendLimit",
688                        nlohmann::json(ReportParams().appendLimit())),
689         std::make_pair(
690             "ReadingParameters",
691             nlohmann::json(
692                 {{{tstring::SensorPath::str(),
693                    {{{tstring::Service::str(), "Service"},
694                      {tstring::Path::str(),
695                       "/xyz/openbmc_project/sensors/power/p1"},
696                      {tstring::Metadata::str(), "metadata1"}}}},
697                   {tstring::OperationType::str(), OperationType::avg},
698                   {tstring::Id::str(), "MetricId1"},
699                   {tstring::CollectionTimeScope::str(),
700                    CollectionTimeScope::point},
701                   {tstring::CollectionDuration::str(), 0}},
702                  {{tstring::SensorPath::str(),
703                    {{{tstring::Service::str(), "Service"},
704                      {tstring::Path::str(),
705                       "/xyz/openbmc_project/sensors/power/p2"},
706                      {tstring::Metadata::str(), "metadata2"}}}},
707                   {tstring::OperationType::str(), OperationType::avg},
708                   {tstring::Id::str(), "MetricId2"},
709                   {tstring::CollectionTimeScope::str(),
710                    CollectionTimeScope::point},
711                   {tstring::CollectionDuration::str(), 0}}}))));
712 
713 TEST_P(TestReportStore, settingPersistencyToTrueStoresReport)
714 {
715     sut = makeReport(defaultParams());
716 
717     {
718         InSequence seq;
719         EXPECT_CALL(storageMock, remove(to_file_path(sut->getId())));
720         EXPECT_CALL(checkPoint, Call());
721         EXPECT_CALL(storageMock, store(to_file_path(sut->getId()), _));
722     }
723 
724     setProperty(sut->getPath(), "Persistency", false);
725     checkPoint.Call();
726     setProperty(sut->getPath(), "Persistency", true);
727 
728     const auto& [key, value] = GetParam();
729 
730     ASSERT_THAT(storedConfiguration.at(key), Eq(value));
731 }
732 
733 TEST_P(TestReportStore, reportIsSavedToStorageAfterCreated)
734 {
735     EXPECT_CALL(storageMock,
736                 store(to_file_path(defaultParams().reportId()), _));
737 
738     sut = makeReport(defaultParams());
739 
740     const auto& [key, value] = GetParam();
741 
742     ASSERT_THAT(storedConfiguration.at(key), Eq(value));
743 }
744 
745 class TestReportValidNames :
746     public TestReport,
747     public WithParamInterface<ReportParams>
748 {
749   public:
750     void SetUp() override
751     {}
752 };
753 
754 INSTANTIATE_TEST_SUITE_P(
755     ValidNames, TestReportValidNames,
756     Values(defaultParams().reportName("Valid_1"),
757            defaultParams().reportName("Valid_1/Valid_2"),
758            defaultParams().reportName("Valid_1/Valid_2/Valid_3")));
759 
760 TEST_P(TestReportValidNames, reportCtorDoesNotThrowOnValidName)
761 {
762     EXPECT_NO_THROW(makeReport(GetParam()));
763 }
764 
765 class TestReportInvalidIds :
766     public TestReport,
767     public WithParamInterface<ReportParams>
768 {
769   public:
770     void SetUp() override
771     {}
772 };
773 
774 INSTANTIATE_TEST_SUITE_P(InvalidNames, TestReportInvalidIds,
775                          Values(defaultParams().reportId("/"),
776                                 defaultParams().reportId("/Invalid"),
777                                 defaultParams().reportId("Invalid/"),
778                                 defaultParams().reportId("Invalid/Invalid/"),
779                                 defaultParams().reportId("Invalid?")));
780 
781 TEST_P(TestReportInvalidIds, failsToCreateReportWithInvalidName)
782 {
783     EXPECT_CALL(storageMock, store).Times(0);
784 
785     EXPECT_THROW(makeReport(GetParam()), sdbusplus::exception::SdBusError);
786 }
787 
788 class TestReportAllReportTypes :
789     public TestReport,
790     public WithParamInterface<ReportParams>
791 {
792   public:
793     void SetUp() override
794     {
795         sut = makeReport(GetParam());
796     }
797 };
798 
799 INSTANTIATE_TEST_SUITE_P(
800     _, TestReportAllReportTypes,
801     Values(defaultParams().reportingType(ReportingType::onRequest),
802            defaultParams().reportingType(ReportingType::onChange),
803            defaultParams()
804                .reportingType(ReportingType::periodic)
805                .interval(ReportManager::minInterval)));
806 
807 TEST_P(TestReportAllReportTypes, returnPropertValueOfReportType)
808 {
809     EXPECT_THAT(utils::toReportingType(
810                     getProperty<std::string>(sut->getPath(), "ReportingType")),
811                 Eq(GetParam().reportingType()));
812 }
813 
814 TEST_P(TestReportAllReportTypes, readingsAreUpdated)
815 {
816     clockFake.system.advance(10ms);
817 
818     messanger.send(messages::UpdateReportInd{{sut->getId()}});
819     const auto [timestamp, readings] =
820         getProperty<Readings>(sut->getPath(), "Readings");
821 
822     EXPECT_THAT(Milliseconds{timestamp}, Eq(systemTimestamp + 10ms));
823 }
824 
825 TEST_P(TestReportAllReportTypes, readingsAreNotUpdatedWhenReportIsDisabled)
826 {
827     clockFake.system.advance(10ms);
828 
829     setProperty(sut->getPath(), "Enabled", false);
830     messanger.send(messages::UpdateReportInd{{sut->getId()}});
831     const auto [timestamp, readings] =
832         getProperty<Readings>(sut->getPath(), "Readings");
833 
834     EXPECT_THAT(Milliseconds{timestamp}, Eq(0ms));
835 }
836 
837 TEST_P(TestReportAllReportTypes, readingsAreNotUpdatedWhenReportIdDiffers)
838 {
839     clockFake.system.advance(10ms);
840 
841     messanger.send(messages::UpdateReportInd{{sut->getId() + "x"s}});
842     const auto [timestamp, readings] =
843         getProperty<Readings>(sut->getPath(), "Readings");
844 
845     EXPECT_THAT(Milliseconds{timestamp}, Eq(0ms));
846 }
847 
848 class TestReportOnRequestType : public TestReport
849 {
850     void SetUp() override
851     {
852         sut =
853             makeReport(defaultParams().reportingType(ReportingType::onRequest));
854     }
855 };
856 
857 TEST_F(TestReportOnRequestType, updatesReadingTimestamp)
858 {
859     clockFake.system.advance(10ms);
860 
861     ASSERT_THAT(update(sut->getPath()), Eq(boost::system::errc::success));
862 
863     const auto [timestamp, readings] =
864         getProperty<Readings>(sut->getPath(), "Readings");
865 
866     EXPECT_THAT(Milliseconds{timestamp}, Eq(systemTimestamp + 10ms));
867 }
868 
869 TEST_F(TestReportOnRequestType, updatesReadingWhenUpdateIsCalled)
870 {
871     ASSERT_THAT(update(sut->getPath()), Eq(boost::system::errc::success));
872 
873     const auto [timestamp, readings] =
874         getProperty<Readings>(sut->getPath(), "Readings");
875 
876     EXPECT_THAT(readings,
877                 ElementsAre(std::make_tuple("a"s, "b"s, 17.1, 114u),
878                             std::make_tuple("aa"s, "bb"s, 42.0, 74u)));
879 }
880 
881 class TestReportNonOnRequestType :
882     public TestReport,
883     public WithParamInterface<ReportParams>
884 {
885     void SetUp() override
886     {
887         sut = makeReport(GetParam());
888     }
889 };
890 
891 INSTANTIATE_TEST_SUITE_P(
892     _, TestReportNonOnRequestType,
893     Values(defaultParams().reportingType(ReportingType::periodic),
894            defaultParams().reportingType(ReportingType::onChange)));
895 
896 TEST_P(TestReportNonOnRequestType, readingsAreNotUpdateOnUpdateCall)
897 {
898     ASSERT_THAT(update(sut->getPath()), Eq(boost::system::errc::success));
899 
900     EXPECT_THAT(getProperty<Readings>(sut->getPath(), "Readings"),
901                 Eq(Readings{}));
902 }
903 
904 class TestReportNonPeriodicReport :
905     public TestReport,
906     public WithParamInterface<ReportParams>
907 {
908   public:
909     void SetUp() override
910     {
911         sut = makeReport(GetParam());
912     }
913 };
914 
915 INSTANTIATE_TEST_SUITE_P(
916     _, TestReportNonPeriodicReport,
917     Values(defaultParams().reportingType(ReportingType::onRequest),
918            defaultParams().reportingType(ReportingType::onChange)));
919 
920 TEST_P(TestReportNonPeriodicReport, readingsAreNotUpdatedAfterIntervalExpires)
921 {
922     DbusEnvironment::sleepFor(ReportManager::minInterval + 1ms);
923 
924     EXPECT_THAT(getProperty<Readings>(sut->getPath(), "Readings"),
925                 Eq(Readings{}));
926 }
927 
928 class TestReportPeriodicReport : public TestReport
929 {
930     void SetUp() override
931     {
932         sut = makeReport(defaultParams()
933                              .reportingType(ReportingType::periodic)
934                              .interval(ReportManager::minInterval));
935     }
936 };
937 
938 TEST_F(TestReportPeriodicReport, readingTimestampIsUpdatedAfterIntervalExpires)
939 {
940     clockFake.system.advance(10ms);
941     DbusEnvironment::sleepFor(ReportManager::minInterval + 1ms);
942 
943     const auto [timestamp, readings] =
944         getProperty<Readings>(sut->getPath(), "Readings");
945 
946     EXPECT_THAT(Milliseconds{timestamp}, Eq(systemTimestamp + 10ms));
947 }
948 
949 TEST_F(TestReportPeriodicReport, readingsAreUpdatedAfterIntervalExpires)
950 {
951     DbusEnvironment::sleepFor(ReportManager::minInterval + 1ms);
952 
953     const auto [timestamp, readings] =
954         getProperty<Readings>(sut->getPath(), "Readings");
955 
956     EXPECT_THAT(readings,
957                 ElementsAre(std::make_tuple("a"s, "b"s, 17.1, 114u),
958                             std::make_tuple("aa"s, "bb"s, 42.0, 74u)));
959 }
960 
961 struct ReportUpdatesReportParams
962 {
963     ReportParams reportParams;
964     std::vector<ReadingData> expectedReadings;
965     bool expectedEnabled;
966 };
967 
968 class TestReportWithReportUpdatesAndLimit :
969     public TestReport,
970     public WithParamInterface<ReportUpdatesReportParams>
971 {
972     void SetUp() override
973     {
974         sut = makeReport(ReportParams(GetParam().reportParams)
975                              .reportingType(ReportingType::periodic)
976                              .interval(std::chrono::hours(1000)));
977     }
978 };
979 
980 INSTANTIATE_TEST_SUITE_P(
981     _, TestReportWithReportUpdatesAndLimit,
982     Values(
983         ReportUpdatesReportParams{
984             defaultParams()
985                 .reportUpdates(ReportUpdates::appendWrapsWhenFull)
986                 .appendLimit(5),
987             std::vector<ReadingData>{{std::make_tuple("aa"s, "bb"s, 42.0, 74u),
988                                       std::make_tuple("a"s, "b"s, 17.1, 114u),
989                                       std::make_tuple("aa"s, "bb"s, 42.0, 74u),
990                                       std::make_tuple("aa"s, "bb"s, 42.0, 74u),
991                                       std::make_tuple("a"s, "b"s, 17.1, 114u)}},
992             true},
993         ReportUpdatesReportParams{
994             defaultParams()
995                 .reportUpdates(ReportUpdates::appendWrapsWhenFull)
996                 .appendLimit(4),
997             std::vector<ReadingData>{
998                 {std::make_tuple("a"s, "b"s, 17.1, 114u),
999                  std::make_tuple("aa"s, "bb"s, 42.0, 74u),
1000                  std::make_tuple("a"s, "b"s, 17.1, 114u),
1001                  std::make_tuple("aa"s, "bb"s, 42.0, 74u)}},
1002             true},
1003         ReportUpdatesReportParams{
1004             defaultParams()
1005                 .reportUpdates(ReportUpdates::appendWrapsWhenFull)
1006                 .appendLimit(0),
1007             std::vector<ReadingData>{}, true},
1008         ReportUpdatesReportParams{
1009             defaultParams()
1010                 .reportUpdates(ReportUpdates::appendStopsWhenFull)
1011                 .appendLimit(10),
1012             std::vector<ReadingData>{
1013                 {std::make_tuple("a"s, "b"s, 17.1, 114u),
1014                  std::make_tuple("aa"s, "bb"s, 42.0, 74u),
1015                  std::make_tuple("a"s, "b"s, 17.1, 114u),
1016                  std::make_tuple("aa"s, "bb"s, 42.0, 74u),
1017                  std::make_tuple("a"s, "b"s, 17.1, 114u),
1018                  std::make_tuple("aa"s, "bb"s, 42.0, 74u),
1019                  std::make_tuple("a"s, "b"s, 17.1, 114u),
1020                  std::make_tuple("aa"s, "bb"s, 42.0, 74u)}},
1021             true},
1022         ReportUpdatesReportParams{
1023             defaultParams()
1024                 .reportUpdates(ReportUpdates::appendStopsWhenFull)
1025                 .appendLimit(5),
1026             std::vector<ReadingData>{{std::make_tuple("a"s, "b"s, 17.1, 114u),
1027                                       std::make_tuple("aa"s, "bb"s, 42.0, 74u),
1028                                       std::make_tuple("a"s, "b"s, 17.1, 114u),
1029                                       std::make_tuple("aa"s, "bb"s, 42.0, 74u),
1030                                       std::make_tuple("a"s, "b"s, 17.1, 114u)}},
1031             false},
1032         ReportUpdatesReportParams{
1033             defaultParams()
1034                 .reportUpdates(ReportUpdates::appendStopsWhenFull)
1035                 .appendLimit(4),
1036             std::vector<ReadingData>{
1037                 {std::make_tuple("a"s, "b"s, 17.1, 114u),
1038                  std::make_tuple("aa"s, "bb"s, 42.0, 74u),
1039                  std::make_tuple("a"s, "b"s, 17.1, 114u),
1040                  std::make_tuple("aa"s, "bb"s, 42.0, 74u)}},
1041             false},
1042         ReportUpdatesReportParams{
1043             defaultParams()
1044                 .reportUpdates(ReportUpdates::appendStopsWhenFull)
1045                 .appendLimit(0),
1046             std::vector<ReadingData>{}, false},
1047         ReportUpdatesReportParams{
1048             defaultParams()
1049                 .reportUpdates(ReportUpdates::overwrite)
1050                 .appendLimit(500),
1051             std::vector<ReadingData>{
1052                 {std::make_tuple("a"s, "b"s, 17.1, 114u),
1053                  std::make_tuple("aa"s, "bb"s, 42.0, 74u)}},
1054             true},
1055         ReportUpdatesReportParams{
1056             defaultParams()
1057                 .reportUpdates(ReportUpdates::overwrite)
1058                 .appendLimit(1),
1059             std::vector<ReadingData>{
1060                 {std::make_tuple("a"s, "b"s, 17.1, 114u),
1061                  std::make_tuple("aa"s, "bb"s, 42.0, 74u)}},
1062             true},
1063         ReportUpdatesReportParams{
1064             defaultParams()
1065                 .reportUpdates(ReportUpdates::overwrite)
1066                 .appendLimit(0),
1067             std::vector<ReadingData>{
1068                 {std::make_tuple("a"s, "b"s, 17.1, 114u),
1069                  std::make_tuple("aa"s, "bb"s, 42.0, 74u)}},
1070             true}));
1071 
1072 TEST_P(TestReportWithReportUpdatesAndLimit,
1073        readingsAreUpdatedAfterIntervalExpires)
1074 {
1075     for (int i = 0; i < 4; i++)
1076     {
1077         messanger.send(messages::UpdateReportInd{{sut->getId()}});
1078     }
1079 
1080     const auto [timestamp, readings] =
1081         getProperty<Readings>(sut->getPath(), "Readings");
1082     const auto enabled = getProperty<bool>(sut->getPath(), "Enabled");
1083 
1084     EXPECT_THAT(readings, ElementsAreArray(GetParam().expectedReadings));
1085     EXPECT_EQ(enabled, GetParam().expectedEnabled);
1086 }
1087 
1088 class TestReportInitialization : public TestReport
1089 {
1090   public:
1091     void SetUp() override
1092     {
1093         initMetricMocks(defaultParams().metricParameters());
1094     }
1095 
1096     void monitorProc(sdbusplus::message_t& msg)
1097     {
1098         std::string iface;
1099         std::vector<std::pair<std::string, std::variant<Readings>>>
1100             changed_properties;
1101         std::vector<std::string> invalidated_properties;
1102 
1103         msg.read(iface, changed_properties, invalidated_properties);
1104 
1105         if (iface == Report::reportIfaceName)
1106         {
1107             for (const auto& [name, value] : changed_properties)
1108             {
1109                 if (name == "Readings")
1110                 {
1111                     readingsUpdated.Call();
1112                 }
1113             }
1114         }
1115     }
1116 
1117     void makeMonitor()
1118     {
1119         monitor = std::make_unique<sdbusplus::bus::match_t>(
1120             *DbusEnvironment::getBus(),
1121             sdbusplus::bus::match::rules::propertiesChanged(
1122                 sut->getPath(), Report::reportIfaceName),
1123             [this](auto& msg) { monitorProc(msg); });
1124     }
1125 
1126     std::unique_ptr<sdbusplus::bus::match_t> monitor;
1127     MockFunction<void()> readingsUpdated;
1128 };
1129 
1130 TEST_F(TestReportInitialization,
1131        registersForMetricUpdatesWhenOnChangeReportCreated)
1132 {
1133     std::vector<const interfaces::MetricListener*> args;
1134     for (auto& metric : metricMocks)
1135     {
1136         EXPECT_CALL(*metric, registerForUpdates(_))
1137             .WillOnce(Invoke([&args](const interfaces::MetricListener& report) {
1138                 args.emplace_back(&report);
1139             }));
1140         ;
1141     }
1142 
1143     sut = makeReport(defaultParams().reportingType(ReportingType::onChange));
1144 
1145     EXPECT_THAT(args, SizeIs(metricMocks.size()));
1146     for (const auto* reportPtr : args)
1147     {
1148         EXPECT_THAT(reportPtr, Eq(sut.get()));
1149     }
1150 }
1151 
1152 TEST_F(TestReportInitialization,
1153        deregistersForMetricUpdatesWhenOnChangeReportDestroyed)
1154 {
1155     sut = makeReport(defaultParams().reportingType(ReportingType::onChange));
1156 
1157     for (auto& metric : metricMocks)
1158     {
1159         EXPECT_CALL(*metric,
1160                     unregisterFromUpdates(Ref(
1161                         static_cast<interfaces::MetricListener&>(*sut.get()))));
1162     }
1163 
1164     sut = nullptr;
1165 }
1166 
1167 TEST_F(TestReportInitialization,
1168        metricsAreInitializedWhenEnabledReportConstructed)
1169 {
1170     for (auto& metric : metricMocks)
1171     {
1172         EXPECT_CALL(*metric, initialize());
1173     }
1174     sut = makeReport(defaultParams().enabled(true));
1175 }
1176 
1177 TEST_F(TestReportInitialization,
1178        metricsAreNotInitializedWhenDisabledReportConstructed)
1179 {
1180     for (auto& metric : metricMocks)
1181     {
1182         EXPECT_CALL(*metric, initialize()).Times(0);
1183     }
1184     sut = makeReport(defaultParams().enabled(false));
1185 }
1186 
1187 TEST_F(TestReportInitialization,
1188        emitReadingsUpdateIsTrueReadingsPropertiesChangedSingalEmits)
1189 {
1190     EXPECT_CALL(readingsUpdated, Call())
1191         .WillOnce(
1192             InvokeWithoutArgs(DbusEnvironment::setPromise("readingsUpdated")));
1193 
1194     const auto elapsed = DbusEnvironment::measureTime([this] {
1195         sut = makeReport(defaultParams()
1196                              .reportingType(ReportingType::periodic)
1197                              .reportActions({ReportAction::emitsReadingsUpdate})
1198                              .interval(ReportManager::minInterval));
1199         makeMonitor();
1200         EXPECT_TRUE(DbusEnvironment::waitForFuture("readingsUpdated"));
1201     });
1202 
1203     EXPECT_THAT(elapsed, AllOf(Ge(ReportManager::minInterval),
1204                                Lt(ReportManager::minInterval * 2)));
1205 }
1206 
1207 TEST_F(TestReportInitialization,
1208        emitReadingsUpdateIsFalseReadingsPropertiesChangesSigalDoesNotEmits)
1209 {
1210     EXPECT_CALL(readingsUpdated, Call()).Times(0);
1211 
1212     sut = makeReport(defaultParams()
1213                          .reportingType(ReportingType::periodic)
1214                          .reportActions({}));
1215     makeMonitor();
1216     DbusEnvironment::sleepFor(defaultParams().interval() * 2);
1217 }
1218 
1219 TEST_F(TestReportInitialization, appendLimitDeducedProperly)
1220 {
1221     sut = makeReport(
1222         defaultParams().appendLimit(std::numeric_limits<uint64_t>::max()));
1223     auto appendLimit = getProperty<uint64_t>(sut->getPath(), "AppendLimit");
1224     EXPECT_EQ(appendLimit, 2ull);
1225 }
1226 
1227 TEST_F(TestReportInitialization, appendLimitSetToUintMaxIsStoredCorrectly)
1228 {
1229     sut = makeReport(
1230         ReportParams().appendLimit(std::numeric_limits<uint64_t>::max()));
1231 
1232     ASSERT_THAT(storedConfiguration.at("AppendLimit"),
1233                 Eq(std::numeric_limits<uint64_t>::max()));
1234 }
1235 
1236 TEST_F(TestReportInitialization, triggerIdsPropertyIsInitialzed)
1237 {
1238     for (const auto& triggerId : {"trigger1", "trigger2"})
1239     {
1240         messanger.on_receive<messages::CollectTriggerIdReq>(
1241             [this, triggerId](const auto& msg) {
1242                 messanger.send(messages::CollectTriggerIdResp{triggerId});
1243             });
1244     }
1245 
1246     sut = makeReport(ReportParams());
1247 
1248     EXPECT_THAT(
1249         getProperty<std::vector<object_path>>(sut->getPath(), "Triggers"),
1250         UnorderedElementsAre(utils::constants::triggerDirPath / "trigger1",
1251                              utils::constants::triggerDirPath / "trigger2"));
1252 }
1253 
1254 TEST_F(TestReportInitialization,
1255        metricValuesAreNotStoredForReportUpdatesDifferentThanAppendStopsWhenFull)
1256 {
1257     sut = makeReport(ReportParams()
1258                          .reportingType(ReportingType::periodic)
1259                          .interval(1h)
1260                          .reportUpdates(ReportUpdates::appendWrapsWhenFull)
1261                          .readings(Readings{{}, {{}}}));
1262 
1263     ASSERT_THAT(storedConfiguration.find("MetricValues"),
1264                 Eq(storedConfiguration.end()));
1265 }
1266 
1267 TEST_F(TestReportInitialization, metricValuesAreNotStoredForOnRequestReport)
1268 {
1269     sut = makeReport(ReportParams()
1270                          .reportingType(ReportingType::onRequest)
1271                          .reportUpdates(ReportUpdates::appendStopsWhenFull)
1272                          .readings(Readings{{}, {{}}}));
1273 
1274     ASSERT_THAT(storedConfiguration.find("MetricValues"),
1275                 Eq(storedConfiguration.end()));
1276 }
1277 
1278 TEST_F(TestReportInitialization,
1279        metricValuesAreStoredForNonOnRequestReportWithAppendStopsWhenFull)
1280 {
1281     const auto readings = Readings{{}, {{}}};
1282 
1283     sut = makeReport(ReportParams()
1284                          .reportingType(ReportingType::periodic)
1285                          .interval(1h)
1286                          .reportUpdates(ReportUpdates::appendStopsWhenFull)
1287                          .readings(readings));
1288 
1289     ASSERT_THAT(storedConfiguration.at("MetricValues").get<LabeledReadings>(),
1290                 Eq(utils::toLabeledReadings(readings)));
1291 }
1292 
1293 class TestReportInitializationOnChangeReport : public TestReportInitialization
1294 {
1295   public:
1296     void SetUp() override
1297     {
1298         initMetricMocks(params.metricParameters());
1299     }
1300 
1301     ReportParams params = defaultOnChangeParams();
1302 };
1303 
1304 TEST_F(TestReportInitializationOnChangeReport,
1305        doesntUpdateReadingsWhenNotRequired)
1306 {
1307     EXPECT_CALL(*metricMocks[0], updateReadings(_)).Times(0);
1308 
1309     ON_CALL(*metricMocks[0], isTimerRequired()).WillByDefault(Return(false));
1310 
1311     sut = makeReport(params);
1312 
1313     DbusEnvironment::sleepFor(500ms);
1314 }
1315 
1316 TEST_F(TestReportInitializationOnChangeReport, updatesReadingsWhenRequired)
1317 {
1318     EXPECT_CALL(*metricMocks[0], updateReadings(_))
1319         .WillOnce(Return())
1320         .WillOnce(
1321             InvokeWithoutArgs(DbusEnvironment::setPromise("readingsUpdated")))
1322         .WillRepeatedly(Return());
1323 
1324     ON_CALL(*metricMocks[0], isTimerRequired()).WillByDefault(Return(true));
1325 
1326     sut = makeReport(params);
1327 
1328     DbusEnvironment::waitForFuture("readingsUpdated");
1329 }
1330