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