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 INSTANTIATE_TEST_SUITE_P( 678 _, TestReportStore, 679 Values( 680 std::make_pair("Enabled"s, nlohmann::json(defaultParams().enabled())), 681 std::make_pair("Version"s, nlohmann::json(7)), 682 std::make_pair("Id"s, nlohmann::json(defaultParams().reportId())), 683 std::make_pair("Name"s, nlohmann::json(defaultParams().reportName())), 684 std::make_pair("ReportingType", 685 nlohmann::json(defaultParams().reportingType())), 686 std::make_pair("ReportActions", nlohmann::json(utils::transform( 687 defaultParams().reportActions(), 688 [](const auto v) { 689 return utils::toUnderlying(v); 690 }))), 691 std::make_pair("Interval", 692 nlohmann::json(defaultParams().interval().count())), 693 std::make_pair("AppendLimit", 694 nlohmann::json(ReportParams().appendLimit())), 695 std::make_pair( 696 "ReadingParameters", 697 nlohmann::json( 698 {{{tstring::SensorPath::str(), 699 {{{tstring::Service::str(), "Service"}, 700 {tstring::Path::str(), 701 "/xyz/openbmc_project/sensors/power/p1"}, 702 {tstring::Metadata::str(), "metadata1"}}}}, 703 {tstring::OperationType::str(), OperationType::avg}, 704 {tstring::Id::str(), "MetricId1"}, 705 {tstring::CollectionTimeScope::str(), 706 CollectionTimeScope::point}, 707 {tstring::CollectionDuration::str(), 0}}, 708 {{tstring::SensorPath::str(), 709 {{{tstring::Service::str(), "Service"}, 710 {tstring::Path::str(), 711 "/xyz/openbmc_project/sensors/power/p2"}, 712 {tstring::Metadata::str(), "metadata2"}}}}, 713 {tstring::OperationType::str(), OperationType::avg}, 714 {tstring::Id::str(), "MetricId2"}, 715 {tstring::CollectionTimeScope::str(), 716 CollectionTimeScope::point}, 717 {tstring::CollectionDuration::str(), 0}}})))); 718 719 TEST_P(TestReportStore, settingPersistencyToTrueStoresReport) 720 { 721 sut = makeReport(defaultParams()); 722 723 { 724 InSequence seq; 725 EXPECT_CALL(storageMock, remove(to_file_path(sut->getId()))); 726 EXPECT_CALL(checkPoint, Call()); 727 EXPECT_CALL(storageMock, store(to_file_path(sut->getId()), _)); 728 } 729 730 setProperty(sut->getPath(), "Persistency", false); 731 checkPoint.Call(); 732 setProperty(sut->getPath(), "Persistency", true); 733 734 const auto& [key, value] = GetParam(); 735 736 ASSERT_THAT(storedConfiguration.at(key), Eq(value)); 737 } 738 739 TEST_P(TestReportStore, reportIsSavedToStorageAfterCreated) 740 { 741 EXPECT_CALL(storageMock, 742 store(to_file_path(defaultParams().reportId()), _)); 743 744 sut = makeReport(defaultParams()); 745 746 const auto& [key, value] = GetParam(); 747 748 ASSERT_THAT(storedConfiguration.at(key), Eq(value)); 749 } 750 751 class TestReportValidNames : 752 public TestReport, 753 public WithParamInterface<ReportParams> 754 { 755 public: 756 void SetUp() override {} 757 }; 758 759 INSTANTIATE_TEST_SUITE_P( 760 ValidNames, TestReportValidNames, 761 Values(defaultParams().reportName("Valid_1"), 762 defaultParams().reportName("Valid_1/Valid_2"), 763 defaultParams().reportName("Valid_1/Valid_2/Valid_3"))); 764 765 TEST_P(TestReportValidNames, reportCtorDoesNotThrowOnValidName) 766 { 767 EXPECT_NO_THROW(makeReport(GetParam())); 768 } 769 770 class TestReportInvalidIds : 771 public TestReport, 772 public WithParamInterface<ReportParams> 773 { 774 public: 775 void SetUp() override {} 776 }; 777 778 INSTANTIATE_TEST_SUITE_P(InvalidNames, TestReportInvalidIds, 779 Values(defaultParams().reportId("/"), 780 defaultParams().reportId("/Invalid"), 781 defaultParams().reportId("Invalid/"), 782 defaultParams().reportId("Invalid/Invalid/"), 783 defaultParams().reportId("Invalid?"))); 784 785 TEST_P(TestReportInvalidIds, failsToCreateReportWithInvalidName) 786 { 787 EXPECT_CALL(storageMock, store).Times(0); 788 789 EXPECT_THROW(makeReport(GetParam()), sdbusplus::exception::SdBusError); 790 } 791 792 class TestReportAllReportTypes : 793 public TestReport, 794 public WithParamInterface<ReportParams> 795 { 796 public: 797 void SetUp() override 798 { 799 sut = makeReport(GetParam()); 800 } 801 }; 802 803 INSTANTIATE_TEST_SUITE_P( 804 _, TestReportAllReportTypes, 805 Values(defaultParams().reportingType(ReportingType::onRequest), 806 defaultParams().reportingType(ReportingType::onChange), 807 defaultParams() 808 .reportingType(ReportingType::periodic) 809 .interval(ReportManager::minInterval))); 810 811 TEST_P(TestReportAllReportTypes, returnPropertValueOfReportType) 812 { 813 EXPECT_THAT(utils::toReportingType( 814 getProperty<std::string>(sut->getPath(), "ReportingType")), 815 Eq(GetParam().reportingType())); 816 } 817 818 TEST_P(TestReportAllReportTypes, readingsAreUpdated) 819 { 820 clockFake.system.advance(10ms); 821 822 messanger.send(messages::UpdateReportInd{{sut->getId()}}); 823 const auto [timestamp, readings] = getProperty<Readings>(sut->getPath(), 824 "Readings"); 825 826 EXPECT_THAT(Milliseconds{timestamp}, Eq(systemTimestamp + 10ms)); 827 } 828 829 TEST_P(TestReportAllReportTypes, readingsAreNotUpdatedWhenReportIsDisabled) 830 { 831 clockFake.system.advance(10ms); 832 833 setProperty(sut->getPath(), "Enabled", false); 834 messanger.send(messages::UpdateReportInd{{sut->getId()}}); 835 const auto [timestamp, readings] = getProperty<Readings>(sut->getPath(), 836 "Readings"); 837 838 EXPECT_THAT(Milliseconds{timestamp}, Eq(0ms)); 839 } 840 841 TEST_P(TestReportAllReportTypes, readingsAreNotUpdatedWhenReportIdDiffers) 842 { 843 clockFake.system.advance(10ms); 844 845 messanger.send(messages::UpdateReportInd{{sut->getId() + "x"s}}); 846 const auto [timestamp, readings] = getProperty<Readings>(sut->getPath(), 847 "Readings"); 848 849 EXPECT_THAT(Milliseconds{timestamp}, Eq(0ms)); 850 } 851 852 class TestReportOnRequestType : public TestReport 853 { 854 void SetUp() override 855 { 856 sut = 857 makeReport(defaultParams().reportingType(ReportingType::onRequest)); 858 } 859 }; 860 861 TEST_F(TestReportOnRequestType, updatesReadingTimestamp) 862 { 863 clockFake.system.advance(10ms); 864 865 ASSERT_THAT(update(sut->getPath()), Eq(boost::system::errc::success)); 866 867 const auto [timestamp, readings] = getProperty<Readings>(sut->getPath(), 868 "Readings"); 869 870 EXPECT_THAT(Milliseconds{timestamp}, Eq(systemTimestamp + 10ms)); 871 } 872 873 TEST_F(TestReportOnRequestType, updatesReadingWhenUpdateIsCalled) 874 { 875 ASSERT_THAT(update(sut->getPath()), Eq(boost::system::errc::success)); 876 877 const auto [timestamp, readings] = getProperty<Readings>(sut->getPath(), 878 "Readings"); 879 880 EXPECT_THAT(readings, 881 ElementsAre(std::make_tuple("a"s, "b"s, 17.1, 114u), 882 std::make_tuple("aa"s, "bb"s, 42.0, 74u))); 883 } 884 885 class TestReportNonOnRequestType : 886 public TestReport, 887 public WithParamInterface<ReportParams> 888 { 889 void SetUp() override 890 { 891 sut = makeReport(GetParam()); 892 } 893 }; 894 895 INSTANTIATE_TEST_SUITE_P( 896 _, TestReportNonOnRequestType, 897 Values(defaultParams().reportingType(ReportingType::periodic), 898 defaultParams().reportingType(ReportingType::onChange))); 899 900 TEST_P(TestReportNonOnRequestType, readingsAreNotUpdateOnUpdateCall) 901 { 902 ASSERT_THAT(update(sut->getPath()), Eq(boost::system::errc::success)); 903 904 EXPECT_THAT(getProperty<Readings>(sut->getPath(), "Readings"), 905 Eq(Readings{})); 906 } 907 908 class TestReportNonPeriodicReport : 909 public TestReport, 910 public WithParamInterface<ReportParams> 911 { 912 public: 913 void SetUp() override 914 { 915 sut = makeReport(GetParam()); 916 } 917 }; 918 919 INSTANTIATE_TEST_SUITE_P( 920 _, TestReportNonPeriodicReport, 921 Values(defaultParams().reportingType(ReportingType::onRequest), 922 defaultParams().reportingType(ReportingType::onChange))); 923 924 TEST_P(TestReportNonPeriodicReport, readingsAreNotUpdatedAfterIntervalExpires) 925 { 926 DbusEnvironment::sleepFor(ReportManager::minInterval + 1ms); 927 928 EXPECT_THAT(getProperty<Readings>(sut->getPath(), "Readings"), 929 Eq(Readings{})); 930 } 931 932 class TestReportPeriodicReport : public TestReport 933 { 934 void SetUp() override 935 { 936 sut = makeReport(defaultParams() 937 .appendLimit(2u) 938 .reportingType(ReportingType::periodic) 939 .interval(ReportManager::minInterval)); 940 } 941 }; 942 943 TEST_F(TestReportPeriodicReport, readingTimestampIsUpdatedAfterIntervalExpires) 944 { 945 clockFake.system.advance(10ms); 946 DbusEnvironment::sleepFor(ReportManager::minInterval + 1ms); 947 948 const auto [timestamp, readings] = getProperty<Readings>(sut->getPath(), 949 "Readings"); 950 951 EXPECT_THAT(Milliseconds{timestamp}, Eq(systemTimestamp + 10ms)); 952 } 953 954 TEST_F(TestReportPeriodicReport, readingsAreUpdatedAfterIntervalExpires) 955 { 956 DbusEnvironment::sleepFor(ReportManager::minInterval + 1ms); 957 958 const auto [timestamp, readings] = getProperty<Readings>(sut->getPath(), 959 "Readings"); 960 961 EXPECT_THAT(readings, 962 ElementsAre(std::make_tuple("a"s, "b"s, 17.1, 114u), 963 std::make_tuple("aa"s, "bb"s, 42.0, 74u))); 964 } 965 966 struct ReportUpdatesReportParams 967 { 968 ReportParams reportParams; 969 std::vector<ReadingData> expectedReadings; 970 bool expectedEnabled; 971 }; 972 973 class TestReportWithReportUpdatesAndLimit : 974 public TestReport, 975 public WithParamInterface<ReportUpdatesReportParams> 976 { 977 public: 978 void SetUp() override {} 979 980 void changeReport(ReportingType rt, Milliseconds interval) 981 { 982 setProperty<std::string>(sut->getPath(), "ReportingType", 983 utils::enumToString(rt)); 984 setProperty<uint64_t>(sut->getPath(), "Interval", interval.count()); 985 } 986 987 auto readings() 988 { 989 auto [timestamp, readings] = getProperty<Readings>(sut->getPath(), 990 "Readings"); 991 return readings; 992 } 993 994 void updateReportFourTimes() 995 { 996 for (int i = 0; i < 4; i++) 997 { 998 messanger.send(messages::UpdateReportInd{{sut->getId()}}); 999 } 1000 } 1001 }; 1002 1003 INSTANTIATE_TEST_SUITE_P( 1004 _, TestReportWithReportUpdatesAndLimit, 1005 Values( 1006 ReportUpdatesReportParams{ 1007 defaultParams() 1008 .reportUpdates(ReportUpdates::appendWrapsWhenFull) 1009 .appendLimit(5), 1010 std::vector<ReadingData>{{std::make_tuple("aa"s, "bb"s, 42.0, 74u), 1011 std::make_tuple("a"s, "b"s, 17.1, 114u), 1012 std::make_tuple("aa"s, "bb"s, 42.0, 74u), 1013 std::make_tuple("aa"s, "bb"s, 42.0, 74u), 1014 std::make_tuple("a"s, "b"s, 17.1, 114u)}}, 1015 true}, 1016 ReportUpdatesReportParams{ 1017 defaultParams() 1018 .reportUpdates(ReportUpdates::appendWrapsWhenFull) 1019 .appendLimit(4), 1020 std::vector<ReadingData>{ 1021 {std::make_tuple("a"s, "b"s, 17.1, 114u), 1022 std::make_tuple("aa"s, "bb"s, 42.0, 74u), 1023 std::make_tuple("a"s, "b"s, 17.1, 114u), 1024 std::make_tuple("aa"s, "bb"s, 42.0, 74u)}}, 1025 true}, 1026 ReportUpdatesReportParams{ 1027 defaultParams() 1028 .reportUpdates(ReportUpdates::appendWrapsWhenFull) 1029 .appendLimit(0), 1030 std::vector<ReadingData>{}, true}, 1031 ReportUpdatesReportParams{ 1032 defaultParams() 1033 .reportUpdates(ReportUpdates::appendStopsWhenFull) 1034 .appendLimit(10), 1035 std::vector<ReadingData>{ 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 std::make_tuple("a"s, "b"s, 17.1, 114u), 1043 std::make_tuple("aa"s, "bb"s, 42.0, 74u)}}, 1044 true}, 1045 ReportUpdatesReportParams{ 1046 defaultParams() 1047 .reportUpdates(ReportUpdates::appendStopsWhenFull) 1048 .appendLimit(5), 1049 std::vector<ReadingData>{{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 std::make_tuple("aa"s, "bb"s, 42.0, 74u), 1053 std::make_tuple("a"s, "b"s, 17.1, 114u)}}, 1054 false}, 1055 ReportUpdatesReportParams{ 1056 defaultParams() 1057 .reportUpdates(ReportUpdates::appendStopsWhenFull) 1058 .appendLimit(4), 1059 std::vector<ReadingData>{ 1060 {std::make_tuple("a"s, "b"s, 17.1, 114u), 1061 std::make_tuple("aa"s, "bb"s, 42.0, 74u), 1062 std::make_tuple("a"s, "b"s, 17.1, 114u), 1063 std::make_tuple("aa"s, "bb"s, 42.0, 74u)}}, 1064 false}, 1065 ReportUpdatesReportParams{ 1066 defaultParams() 1067 .reportUpdates(ReportUpdates::appendStopsWhenFull) 1068 .appendLimit(0), 1069 std::vector<ReadingData>{}, false}, 1070 ReportUpdatesReportParams{ 1071 defaultParams() 1072 .reportUpdates(ReportUpdates::overwrite) 1073 .appendLimit(500), 1074 std::vector<ReadingData>{ 1075 {std::make_tuple("a"s, "b"s, 17.1, 114u), 1076 std::make_tuple("aa"s, "bb"s, 42.0, 74u)}}, 1077 true}, 1078 ReportUpdatesReportParams{ 1079 defaultParams() 1080 .reportUpdates(ReportUpdates::overwrite) 1081 .appendLimit(1), 1082 std::vector<ReadingData>{ 1083 {std::make_tuple("a"s, "b"s, 17.1, 114u), 1084 std::make_tuple("aa"s, "bb"s, 42.0, 74u)}}, 1085 true}, 1086 ReportUpdatesReportParams{ 1087 defaultParams() 1088 .reportUpdates(ReportUpdates::overwrite) 1089 .appendLimit(0), 1090 std::vector<ReadingData>{ 1091 {std::make_tuple("a"s, "b"s, 17.1, 114u), 1092 std::make_tuple("aa"s, "bb"s, 42.0, 74u)}}, 1093 true}, 1094 ReportUpdatesReportParams{ 1095 defaultParams() 1096 .reportUpdates(ReportUpdates::appendStopsWhenFull) 1097 .appendLimit(2u), 1098 std::vector<ReadingData>{ 1099 {std::make_tuple("a"s, "b"s, 17.1, 114u), 1100 std::make_tuple("aa"s, "bb"s, 42.0, 74u)}}, 1101 false})); 1102 1103 TEST_P(TestReportWithReportUpdatesAndLimit, 1104 readingsAreUpdatedAfterIntervalExpires) 1105 { 1106 sut = makeReport(ReportParams(GetParam().reportParams) 1107 .reportingType(ReportingType::periodic) 1108 .interval(std::chrono::hours(1000))); 1109 1110 updateReportFourTimes(); 1111 1112 EXPECT_THAT(readings(), ElementsAreArray(GetParam().expectedReadings)); 1113 EXPECT_THAT(getProperty<bool>(sut->getPath(), "Enabled"), 1114 Eq(GetParam().expectedEnabled)); 1115 } 1116 1117 TEST_P(TestReportWithReportUpdatesAndLimit, 1118 appendLimitIsRespectedAfterChangingToPeriodic) 1119 { 1120 sut = makeReport(ReportParams(GetParam().reportParams) 1121 .appendLimit(GetParam().expectedReadings.size()) 1122 .reportingType(ReportingType::onRequest) 1123 .interval(std::chrono::hours(0))); 1124 1125 changeReport(ReportingType::periodic, std::chrono::hours(1000)); 1126 updateReportFourTimes(); 1127 1128 EXPECT_THAT(readings(), ElementsAreArray(GetParam().expectedReadings)); 1129 EXPECT_THAT(getProperty<bool>(sut->getPath(), "Enabled"), 1130 Eq(GetParam().expectedEnabled)); 1131 } 1132 1133 TEST_P(TestReportWithReportUpdatesAndLimit, 1134 appendLimitIsIgnoredAfterChangingToOnRequest) 1135 { 1136 sut = makeReport(ReportParams(GetParam().reportParams) 1137 .reportingType(ReportingType::periodic) 1138 .interval(std::chrono::hours(1000))); 1139 1140 changeReport(ReportingType::onRequest, Milliseconds{0}); 1141 updateReportFourTimes(); 1142 1143 EXPECT_THAT(readings(), SizeIs(2u)); 1144 EXPECT_THAT(getProperty<bool>(sut->getPath(), "Enabled"), Eq(true)); 1145 } 1146 1147 class TestReportInitialization : public TestReport 1148 { 1149 public: 1150 void SetUp() override 1151 { 1152 initMetricMocks(defaultParams().metricParameters()); 1153 } 1154 1155 void monitorProc(sdbusplus::message_t& msg) 1156 { 1157 std::string iface; 1158 std::vector<std::pair<std::string, std::variant<Readings>>> 1159 changed_properties; 1160 std::vector<std::string> invalidated_properties; 1161 1162 msg.read(iface, changed_properties, invalidated_properties); 1163 1164 if (iface == Report::reportIfaceName) 1165 { 1166 for (const auto& [name, value] : changed_properties) 1167 { 1168 if (name == "Readings") 1169 { 1170 readingsUpdated.Call(); 1171 } 1172 } 1173 } 1174 } 1175 1176 void makeMonitor() 1177 { 1178 monitor = std::make_unique<sdbusplus::bus::match_t>( 1179 *DbusEnvironment::getBus(), 1180 sdbusplus::bus::match::rules::propertiesChanged( 1181 sut->getPath(), Report::reportIfaceName), 1182 [this](auto& msg) { monitorProc(msg); }); 1183 } 1184 1185 std::unique_ptr<sdbusplus::bus::match_t> monitor; 1186 MockFunction<void()> readingsUpdated; 1187 }; 1188 1189 TEST_F(TestReportInitialization, 1190 registersForMetricUpdatesWhenOnChangeReportCreated) 1191 { 1192 std::vector<const interfaces::MetricListener*> args; 1193 for (auto& metric : metricMocks) 1194 { 1195 EXPECT_CALL(*metric, registerForUpdates(_)) 1196 .WillOnce(Invoke([&args](const interfaces::MetricListener& report) { 1197 args.emplace_back(&report); 1198 })); 1199 ; 1200 } 1201 1202 sut = makeReport(defaultParams().reportingType(ReportingType::onChange)); 1203 1204 EXPECT_THAT(args, SizeIs(metricMocks.size())); 1205 for (const auto* reportPtr : args) 1206 { 1207 EXPECT_THAT(reportPtr, Eq(sut.get())); 1208 } 1209 } 1210 1211 TEST_F(TestReportInitialization, 1212 deregistersForMetricUpdatesWhenOnChangeReportDestroyed) 1213 { 1214 sut = makeReport(defaultParams().reportingType(ReportingType::onChange)); 1215 1216 for (auto& metric : metricMocks) 1217 { 1218 EXPECT_CALL(*metric, 1219 unregisterFromUpdates(Ref( 1220 static_cast<interfaces::MetricListener&>(*sut.get())))); 1221 } 1222 1223 sut = nullptr; 1224 } 1225 1226 TEST_F(TestReportInitialization, 1227 metricsAreInitializedWhenEnabledReportConstructed) 1228 { 1229 for (auto& metric : metricMocks) 1230 { 1231 EXPECT_CALL(*metric, initialize()); 1232 } 1233 sut = makeReport(defaultParams().enabled(true)); 1234 } 1235 1236 TEST_F(TestReportInitialization, 1237 metricsAreNotInitializedWhenDisabledReportConstructed) 1238 { 1239 for (auto& metric : metricMocks) 1240 { 1241 EXPECT_CALL(*metric, initialize()).Times(0); 1242 } 1243 sut = makeReport(defaultParams().enabled(false)); 1244 } 1245 1246 TEST_F(TestReportInitialization, 1247 emitReadingsUpdateIsTrueReadingsPropertiesChangedSingalEmits) 1248 { 1249 EXPECT_CALL(readingsUpdated, Call()) 1250 .WillOnce( 1251 InvokeWithoutArgs(DbusEnvironment::setPromise("readingsUpdated"))); 1252 1253 const auto elapsed = DbusEnvironment::measureTime([this] { 1254 sut = makeReport(defaultParams() 1255 .reportingType(ReportingType::periodic) 1256 .reportActions({ReportAction::emitsReadingsUpdate}) 1257 .interval(ReportManager::minInterval)); 1258 makeMonitor(); 1259 EXPECT_TRUE(DbusEnvironment::waitForFuture("readingsUpdated")); 1260 }); 1261 1262 EXPECT_THAT(elapsed, AllOf(Ge(ReportManager::minInterval), 1263 Lt(ReportManager::minInterval * 2))); 1264 } 1265 1266 TEST_F(TestReportInitialization, 1267 emitReadingsUpdateIsFalseReadingsPropertiesChangesSigalDoesNotEmits) 1268 { 1269 EXPECT_CALL(readingsUpdated, Call()).Times(0); 1270 1271 sut = makeReport(defaultParams() 1272 .reportingType(ReportingType::periodic) 1273 .reportActions({})); 1274 makeMonitor(); 1275 DbusEnvironment::sleepFor(defaultParams().interval() * 2); 1276 } 1277 1278 TEST_F(TestReportInitialization, triggerIdsPropertyIsInitialzed) 1279 { 1280 for (const auto& triggerId : {"trigger1", "trigger2"}) 1281 { 1282 messanger.on_receive<messages::CollectTriggerIdReq>( 1283 [this, triggerId](const auto& msg) { 1284 messanger.send(messages::CollectTriggerIdResp{triggerId}); 1285 }); 1286 } 1287 1288 sut = makeReport(ReportParams()); 1289 1290 EXPECT_THAT( 1291 getProperty<std::vector<object_path>>(sut->getPath(), "Triggers"), 1292 UnorderedElementsAre(utils::constants::triggerDirPath / "trigger1", 1293 utils::constants::triggerDirPath / "trigger2")); 1294 } 1295 1296 TEST_F(TestReportInitialization, 1297 metricValuesAreNotStoredForReportUpdatesDifferentThanAppendStopsWhenFull) 1298 { 1299 sut = makeReport(ReportParams() 1300 .reportingType(ReportingType::periodic) 1301 .interval(1h) 1302 .reportUpdates(ReportUpdates::appendWrapsWhenFull) 1303 .readings(Readings{{}, {{}}})); 1304 1305 ASSERT_THAT(storedConfiguration.find("MetricValues"), 1306 Eq(storedConfiguration.end())); 1307 } 1308 1309 TEST_F(TestReportInitialization, metricValuesAreNotStoredForOnRequestReport) 1310 { 1311 sut = makeReport(ReportParams() 1312 .reportingType(ReportingType::onRequest) 1313 .reportUpdates(ReportUpdates::appendStopsWhenFull) 1314 .readings(Readings{{}, {{}}})); 1315 1316 ASSERT_THAT(storedConfiguration.find("MetricValues"), 1317 Eq(storedConfiguration.end())); 1318 } 1319 1320 TEST_F(TestReportInitialization, 1321 metricValuesAreStoredForNonOnRequestReportWithAppendStopsWhenFull) 1322 { 1323 const auto readings = Readings{{}, {{}}}; 1324 1325 sut = makeReport(ReportParams() 1326 .reportingType(ReportingType::periodic) 1327 .interval(1h) 1328 .reportUpdates(ReportUpdates::appendStopsWhenFull) 1329 .readings(readings)); 1330 1331 ASSERT_THAT(storedConfiguration.at("MetricValues").get<LabeledReadings>(), 1332 Eq(utils::toLabeledReadings(readings))); 1333 } 1334 1335 class TestReportInitializationOnChangeReport : public TestReportInitialization 1336 { 1337 public: 1338 void SetUp() override 1339 { 1340 initMetricMocks(params.metricParameters()); 1341 } 1342 1343 ReportParams params = defaultOnChangeParams(); 1344 }; 1345 1346 TEST_F(TestReportInitializationOnChangeReport, 1347 doesntUpdateReadingsWhenNotRequired) 1348 { 1349 EXPECT_CALL(*metricMocks[0], updateReadings(_)).Times(0); 1350 1351 ON_CALL(*metricMocks[0], isTimerRequired()).WillByDefault(Return(false)); 1352 1353 sut = makeReport(params); 1354 1355 DbusEnvironment::sleepFor(500ms); 1356 } 1357 1358 TEST_F(TestReportInitializationOnChangeReport, updatesReadingsWhenRequired) 1359 { 1360 EXPECT_CALL(*metricMocks[0], updateReadings(_)) 1361 .WillOnce(Return()) 1362 .WillOnce( 1363 InvokeWithoutArgs(DbusEnvironment::setPromise("readingsUpdated"))) 1364 .WillRepeatedly(Return()); 1365 1366 ON_CALL(*metricMocks[0], isTimerRequired()).WillByDefault(Return(true)); 1367 1368 sut = makeReport(params); 1369 1370 DbusEnvironment::waitForFuture("readingsUpdated"); 1371 } 1372