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