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