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