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