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