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