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