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