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