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