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