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