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