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