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