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