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