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