blob: 675171a6091a8368b75fe817ce42a57a3738261f [file] [log] [blame]
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +02001#include "dbus_environment.hpp"
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +01002#include "fakes/clock_fake.hpp"
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +00003#include "helpers.hpp"
Wludzik, Jozefe2362792020-10-27 17:23:55 +01004#include "mocks/json_storage_mock.hpp"
Krzysztof Grobelnyc8e3a642020-10-23 12:29:16 +02005#include "mocks/metric_mock.hpp"
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +02006#include "mocks/report_manager_mock.hpp"
Krzysztof Grobelnyc8e3a642020-10-23 12:29:16 +02007#include "params/report_params.hpp"
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +02008#include "report.hpp"
9#include "report_manager.hpp"
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +010010#include "utils/clock.hpp"
Krzysztof Grobelny51497a02021-11-09 14:56:22 +010011#include "utils/contains.hpp"
Krzysztof Grobelnyc8e3a642020-10-23 12:29:16 +020012#include "utils/conv_container.hpp"
Krzysztof Grobelny51497a02021-11-09 14:56:22 +010013#include "utils/transform.hpp"
Krzysztof Grobelnye8fc5752021-02-05 14:30:45 +000014#include "utils/tstring.hpp"
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +020015
16#include <sdbusplus/exception.hpp>
17
18using namespace testing;
19using namespace std::literals::string_literals;
Krzysztof Grobelnyc8e3a642020-10-23 12:29:16 +020020using namespace std::chrono_literals;
Krzysztof Grobelnye8fc5752021-02-05 14:30:45 +000021namespace tstring = utils::tstring;
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +020022
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +010023constexpr Milliseconds systemTimestamp = 55ms;
24
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +020025class TestReport : public Test
26{
27 public:
Wludzik, Jozefe2362792020-10-27 17:23:55 +010028 ReportParams defaultParams;
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +020029
30 std::unique_ptr<ReportManagerMock> reportManagerMock =
Wludzik, Jozefe2362792020-10-27 17:23:55 +010031 std::make_unique<NiceMock<ReportManagerMock>>();
32 testing::NiceMock<StorageMock> storageMock;
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +000033 std::vector<std::shared_ptr<MetricMock>> metricMocks;
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +010034 std::unique_ptr<ClockFake> clockFakePtr = std::make_unique<ClockFake>();
35 ClockFake& clockFake = *clockFakePtr;
Krzysztof Grobelnyc8e3a642020-10-23 12:29:16 +020036 std::unique_ptr<Report> sut;
37
Wludzik, Jozefe2362792020-10-27 17:23:55 +010038 MockFunction<void()> checkPoint;
39
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +010040 TestReport()
41 {
42 clockFake.system.set(systemTimestamp);
43 }
44
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +000045 void initMetricMocks(
46 const std::vector<LabeledMetricParameters>& metricParameters)
Wludzik, Jozefe2362792020-10-27 17:23:55 +010047 {
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +000048 for (auto i = metricMocks.size(); i < metricParameters.size(); ++i)
Wludzik, Jozefe2362792020-10-27 17:23:55 +010049 {
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +000050 metricMocks.emplace_back(std::make_shared<NiceMock<MetricMock>>());
51 }
52 metricMocks.resize(metricParameters.size());
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +000053
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +000054 std::vector<MetricValue> readings{{MetricValue{"a", "b", 17.1, 114},
55 MetricValue{"aa", "bb", 42.0, 74}}};
56 readings.resize(metricParameters.size());
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +000057
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +000058 for (size_t i = 0; i < metricParameters.size(); ++i)
59 {
60 ON_CALL(*metricMocks[i], getReadings())
Krzysztof Grobelny80697712021-03-04 09:49:27 +000061 .WillByDefault(Return(std::vector({readings[i]})));
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +000062 ON_CALL(*metricMocks[i], dumpConfiguration())
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +000063 .WillByDefault(Return(metricParameters[i]));
Wludzik, Jozefe2362792020-10-27 17:23:55 +010064 }
65 }
66
Krzysztof Grobelnyc8e3a642020-10-23 12:29:16 +020067 void SetUp() override
68 {
69 sut = makeReport(ReportParams());
70 }
71
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +010072 static interfaces::JsonStorage::FilePath to_file_path(std::string id)
Wludzik, Jozefe2362792020-10-27 17:23:55 +010073 {
74 return interfaces::JsonStorage::FilePath(
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +010075 std::to_string(std::hash<std::string>{}(id)));
Wludzik, Jozefe2362792020-10-27 17:23:55 +010076 }
77
Krzysztof Grobelnyc8e3a642020-10-23 12:29:16 +020078 std::unique_ptr<Report> makeReport(const ReportParams& params)
79 {
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +000080 initMetricMocks(params.metricParameters());
81
Krzysztof Grobelnyc8e3a642020-10-23 12:29:16 +020082 return std::make_unique<Report>(
83 DbusEnvironment::getIoc(), DbusEnvironment::getObjServer(),
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +010084 params.reportId(), params.reportName(), params.reportingType(),
85 params.reportActions(), params.interval(), params.appendLimit(),
86 params.reportUpdates(), *reportManagerMock, storageMock,
Krzysztof Grobelnyc8e3a642020-10-23 12:29:16 +020087 utils::convContainer<std::shared_ptr<interfaces::Metric>>(
Lukasz Kazmierczak7e098e92021-09-16 15:59:56 +020088 metricMocks),
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +010089 params.enabled(), std::move(clockFakePtr));
Krzysztof Grobelnyc8e3a642020-10-23 12:29:16 +020090 }
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +020091
92 template <class T>
93 static T getProperty(const std::string& path, const std::string& property)
94 {
Szymon Dompkee28aa532021-10-27 12:33:12 +020095 return DbusEnvironment::getProperty<T>(path, Report::reportIfaceName,
96 property);
97 }
98
99 template <class T>
100 static boost::system::error_code setProperty(const std::string& path,
101 const std::string& property,
102 const T& newValue)
103 {
104 return DbusEnvironment::setProperty<T>(path, Report::reportIfaceName,
105 property, newValue);
Krzysztof Grobelnyf32f6fe2020-10-30 13:51:58 +0100106 }
107
108 boost::system::error_code call(const std::string& path,
109 const std::string& interface,
110 const std::string& method)
111 {
112 std::promise<boost::system::error_code> methodPromise;
113 DbusEnvironment::getBus()->async_method_call(
114 [&methodPromise](boost::system::error_code ec) {
115 methodPromise.set_value(ec);
116 },
117 DbusEnvironment::serviceName(), path, interface, method);
118 return DbusEnvironment::waitForFuture(methodPromise.get_future());
119 }
120
121 boost::system::error_code update(const std::string& path)
122 {
123 return call(path, Report::reportIfaceName, "Update");
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +0200124 }
125
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +0200126 boost::system::error_code deleteReport(const std::string& path)
127 {
Krzysztof Grobelnyf32f6fe2020-10-30 13:51:58 +0100128 return call(path, Report::deleteIfaceName, "Delete");
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +0200129 }
130};
131
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +0100132TEST_F(TestReport, returnsId)
133{
134 EXPECT_THAT(sut->getId(), Eq(defaultParams.reportId()));
135}
136
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +0200137TEST_F(TestReport, verifyIfPropertiesHaveValidValue)
138{
Lukasz Kazmierczak7e098e92021-09-16 15:59:56 +0200139 EXPECT_THAT(getProperty<bool>(sut->getPath(), "Enabled"),
140 Eq(defaultParams.enabled()));
Krzysztof Grobelnyc8e3a642020-10-23 12:29:16 +0200141 EXPECT_THAT(getProperty<uint64_t>(sut->getPath(), "Interval"),
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100142 Eq(defaultParams.interval().count()));
143 EXPECT_THAT(getProperty<bool>(sut->getPath(), "Persistency"), Eq(true));
Krzysztof Grobelny51497a02021-11-09 14:56:22 +0100144 EXPECT_THAT(
145 getProperty<std::vector<std::string>>(sut->getPath(), "ReportActions"),
146 Eq(utils::transform(defaultParams.reportActions(), [](const auto v) {
147 return utils::enumToString(v);
148 })));
Krzysztof Grobelnyc8e3a642020-10-23 12:29:16 +0200149 EXPECT_THAT(getProperty<bool>(sut->getPath(), "EmitsReadingsUpdate"),
Krzysztof Grobelny51497a02021-11-09 14:56:22 +0100150 Eq(utils::contains(defaultParams.reportActions(),
151 ReportAction::emitsReadingsUpdate)));
Szymon Dompke3eb56862021-09-20 15:32:04 +0200152 EXPECT_THAT(getProperty<uint64_t>(sut->getPath(), "AppendLimit"),
153 Eq(defaultParams.appendLimit()));
Krzysztof Grobelny51497a02021-11-09 14:56:22 +0100154 EXPECT_THAT(getProperty<std::string>(sut->getPath(), "ReportingType"),
155 Eq(utils::enumToString(defaultParams.reportingType())));
Szymon Dompke3eb56862021-09-20 15:32:04 +0200156 EXPECT_THAT(getProperty<std::string>(sut->getPath(), "ReportUpdates"),
Krzysztof Grobelny51497a02021-11-09 14:56:22 +0100157 Eq(utils::enumToString(defaultParams.reportUpdates())));
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +0200158 EXPECT_THAT(
Krzysztof Grobelnyc8e3a642020-10-23 12:29:16 +0200159 getProperty<bool>(sut->getPath(), "LogToMetricReportsCollection"),
Krzysztof Grobelny51497a02021-11-09 14:56:22 +0100160 Eq(utils::contains(defaultParams.reportActions(),
161 ReportAction::logToMetricReportsCollection)));
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000162 EXPECT_THAT(getProperty<ReadingParameters>(
163 sut->getPath(), "ReadingParametersFutureVersion"),
164 Eq(toReadingParameters(defaultParams.metricParameters())));
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +0100165 EXPECT_THAT(getProperty<std::string>(sut->getPath(), "Name"),
166 Eq(defaultParams.reportName()));
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +0200167}
168
Krzysztof Grobelnyc8e3a642020-10-23 12:29:16 +0200169TEST_F(TestReport, readingsAreInitialyEmpty)
170{
171 EXPECT_THAT(getProperty<Readings>(sut->getPath(), "Readings"),
172 Eq(Readings{}));
173}
174
Lukasz Kazmierczak7e098e92021-09-16 15:59:56 +0200175TEST_F(TestReport, setEnabledWithNewValue)
176{
177 bool newValue = !defaultParams.enabled();
178 EXPECT_THAT(setProperty(sut->getPath(), "Enabled", newValue).value(),
179 Eq(boost::system::errc::success));
180 EXPECT_THAT(getProperty<bool>(sut->getPath(), "Enabled"), Eq(newValue));
181}
182
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +0200183TEST_F(TestReport, setIntervalWithValidValue)
184{
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100185 uint64_t newValue = defaultParams.interval().count() + 1;
Krzysztof Grobelnyc8e3a642020-10-23 12:29:16 +0200186 EXPECT_THAT(setProperty(sut->getPath(), "Interval", newValue).value(),
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +0200187 Eq(boost::system::errc::success));
Krzysztof Grobelnyc8e3a642020-10-23 12:29:16 +0200188 EXPECT_THAT(getProperty<uint64_t>(sut->getPath(), "Interval"),
189 Eq(newValue));
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +0200190}
191
Szymon Dompke3e2cc9d2021-12-14 12:00:52 +0100192TEST_F(
193 TestReport,
194 settingIntervalWithInvalidValueDoesNotChangePropertyAndReturnsInvalidArgument)
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +0200195{
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100196 uint64_t newValue = defaultParams.interval().count() - 1;
Krzysztof Grobelnyc8e3a642020-10-23 12:29:16 +0200197 EXPECT_THAT(setProperty(sut->getPath(), "Interval", newValue).value(),
Szymon Dompke3e2cc9d2021-12-14 12:00:52 +0100198 Eq(boost::system::errc::invalid_argument));
Krzysztof Grobelnyc8e3a642020-10-23 12:29:16 +0200199 EXPECT_THAT(getProperty<uint64_t>(sut->getPath(), "Interval"),
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100200 Eq(defaultParams.interval().count()));
201}
202
Wludzik, Jozefb1ff1f62020-10-23 13:20:52 +0200203TEST_F(TestReport, settingEmitsReadingsUpdateHaveNoEffect)
204{
Krzysztof Grobelny51497a02021-11-09 14:56:22 +0100205 EXPECT_THAT(
206 setProperty(sut->getPath(), "EmitsReadingsUpdate", true).value(),
207 Eq(boost::system::errc::read_only_file_system));
Wludzik, Jozefb1ff1f62020-10-23 13:20:52 +0200208 EXPECT_THAT(getProperty<bool>(sut->getPath(), "EmitsReadingsUpdate"),
Krzysztof Grobelny51497a02021-11-09 14:56:22 +0100209 Eq(utils::contains(defaultParams.reportActions(),
210 ReportAction::emitsReadingsUpdate)));
Wludzik, Jozefb1ff1f62020-10-23 13:20:52 +0200211}
212
213TEST_F(TestReport, settingLogToMetricReportCollectionHaveNoEffect)
214{
Krzysztof Grobelny51497a02021-11-09 14:56:22 +0100215 EXPECT_THAT(
216 setProperty(sut->getPath(), "LogToMetricReportsCollection", true)
217 .value(),
218 Eq(boost::system::errc::read_only_file_system));
Wludzik, Jozefb1ff1f62020-10-23 13:20:52 +0200219 EXPECT_THAT(
220 getProperty<bool>(sut->getPath(), "LogToMetricReportsCollection"),
Krzysztof Grobelny51497a02021-11-09 14:56:22 +0100221 Eq(utils::contains(defaultParams.reportActions(),
222 ReportAction::logToMetricReportsCollection)));
Wludzik, Jozefb1ff1f62020-10-23 13:20:52 +0200223}
224
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100225TEST_F(TestReport, settingPersistencyToFalseRemovesReportFromStorage)
226{
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +0100227 EXPECT_CALL(storageMock, remove(to_file_path(sut->getId())));
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100228
229 bool persistency = false;
230 EXPECT_THAT(setProperty(sut->getPath(), "Persistency", persistency).value(),
231 Eq(boost::system::errc::success));
232 EXPECT_THAT(getProperty<bool>(sut->getPath(), "Persistency"),
233 Eq(persistency));
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +0200234}
235
236TEST_F(TestReport, deleteReport)
237{
Krzysztof Grobelnyc8e3a642020-10-23 12:29:16 +0200238 EXPECT_CALL(*reportManagerMock, removeReport(sut.get()));
239 auto ec = deleteReport(sut->getPath());
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +0200240 EXPECT_THAT(ec, Eq(boost::system::errc::success));
241}
242
243TEST_F(TestReport, deletingNonExistingReportReturnInvalidRequestDescriptor)
244{
245 auto ec = deleteReport(Report::reportDir + "NonExisting"s);
246 EXPECT_THAT(ec.value(), Eq(EBADR));
247}
248
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100249TEST_F(TestReport, deleteReportExpectThatFileIsRemoveFromStorage)
250{
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +0100251 EXPECT_CALL(storageMock, remove(to_file_path(sut->getId())));
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100252 auto ec = deleteReport(sut->getPath());
253 EXPECT_THAT(ec, Eq(boost::system::errc::success));
254}
255
256class TestReportStore :
257 public TestReport,
258 public WithParamInterface<std::pair<std::string, nlohmann::json>>
259{
260 public:
261 void SetUp() override
262 {}
263
264 nlohmann::json storedConfiguration;
265};
266
267INSTANTIATE_TEST_SUITE_P(
268 _, TestReportStore,
Lukasz Kazmierczak7e098e92021-09-16 15:59:56 +0200269 Values(std::make_pair("Enabled"s, nlohmann::json(ReportParams().enabled())),
Krzysztof Grobelny51497a02021-11-09 14:56:22 +0100270 std::make_pair("Version"s, nlohmann::json(6)),
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +0100271 std::make_pair("Id"s, nlohmann::json(ReportParams().reportId())),
Krzysztof Grobelnye8fc5752021-02-05 14:30:45 +0000272 std::make_pair("Name"s, nlohmann::json(ReportParams().reportName())),
273 std::make_pair("ReportingType",
274 nlohmann::json(ReportParams().reportingType())),
Krzysztof Grobelny51497a02021-11-09 14:56:22 +0100275 std::make_pair("ReportActions", nlohmann::json(utils::transform(
276 ReportParams().reportActions(),
277 [](const auto v) {
278 return utils::toUnderlying(
279 v);
280 }))),
Krzysztof Grobelnye8fc5752021-02-05 14:30:45 +0000281 std::make_pair("Interval",
282 nlohmann::json(ReportParams().interval().count())),
283 std::make_pair(
284 "ReadingParameters",
285 nlohmann::json(
286 {{{tstring::SensorPath::str(),
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000287 {{{tstring::Service::str(), "Service"},
288 {tstring::Path::str(),
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +0100289 "/xyz/openbmc_project/sensors/power/p1"},
290 {tstring::Metadata::str(), "metadata1"}}}},
Krzysztof Grobelnye8fc5752021-02-05 14:30:45 +0000291 {tstring::OperationType::str(), OperationType::single},
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000292 {tstring::Id::str(), "MetricId1"},
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000293 {tstring::CollectionTimeScope::str(),
294 CollectionTimeScope::point},
295 {tstring::CollectionDuration::str(), 0}},
Krzysztof Grobelnye8fc5752021-02-05 14:30:45 +0000296 {{tstring::SensorPath::str(),
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000297 {{{tstring::Service::str(), "Service"},
298 {tstring::Path::str(),
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +0100299 "/xyz/openbmc_project/sensors/power/p2"},
300 {tstring::Metadata::str(), "metadata2"}}}},
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000301 {tstring::OperationType::str(), OperationType::single},
302 {tstring::Id::str(), "MetricId2"},
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000303 {tstring::CollectionTimeScope::str(),
304 CollectionTimeScope::point},
305 {tstring::CollectionDuration::str(), 0}}}))));
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100306
307TEST_P(TestReportStore, settingPersistencyToTrueStoresReport)
308{
309 sut = makeReport(ReportParams());
310
311 {
312 InSequence seq;
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +0100313 EXPECT_CALL(storageMock, remove(to_file_path(sut->getId())));
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100314 EXPECT_CALL(checkPoint, Call());
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +0100315 EXPECT_CALL(storageMock, store(to_file_path(sut->getId()), _))
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100316 .WillOnce(SaveArg<1>(&storedConfiguration));
317 }
318
319 setProperty(sut->getPath(), "Persistency", false);
320 checkPoint.Call();
321 setProperty(sut->getPath(), "Persistency", true);
322
323 const auto& [key, value] = GetParam();
324
325 ASSERT_THAT(storedConfiguration.at(key), Eq(value));
326}
327
328TEST_P(TestReportStore, reportIsSavedToStorageAfterCreated)
329{
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +0100330 EXPECT_CALL(storageMock, store(to_file_path(ReportParams().reportId()), _))
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100331 .WillOnce(SaveArg<1>(&storedConfiguration));
332
333 sut = makeReport(ReportParams());
334
335 const auto& [key, value] = GetParam();
336
337 ASSERT_THAT(storedConfiguration.at(key), Eq(value));
338}
339
Krzysztof Grobelnyc8e3a642020-10-23 12:29:16 +0200340class TestReportValidNames :
341 public TestReport,
342 public WithParamInterface<ReportParams>
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +0200343{
344 public:
Krzysztof Grobelnyc8e3a642020-10-23 12:29:16 +0200345 void SetUp() override
346 {}
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +0200347};
348
Krzysztof Grobelnyc8e3a642020-10-23 12:29:16 +0200349INSTANTIATE_TEST_SUITE_P(
350 ValidNames, TestReportValidNames,
351 Values(ReportParams().reportName("Valid_1"),
352 ReportParams().reportName("Valid_1/Valid_2"),
353 ReportParams().reportName("Valid_1/Valid_2/Valid_3")));
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +0200354
355TEST_P(TestReportValidNames, reportCtorDoesNotThrowOnValidName)
356{
Krzysztof Grobelnyc8e3a642020-10-23 12:29:16 +0200357 EXPECT_NO_THROW(makeReport(GetParam()));
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +0200358}
359
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +0100360class TestReportInvalidIds :
Krzysztof Grobelnyc8e3a642020-10-23 12:29:16 +0200361 public TestReport,
362 public WithParamInterface<ReportParams>
363{
364 public:
365 void SetUp() override
366 {}
367};
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +0200368
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +0100369INSTANTIATE_TEST_SUITE_P(InvalidNames, TestReportInvalidIds,
370 Values(ReportParams().reportId("/"),
371 ReportParams().reportId("/Invalid"),
372 ReportParams().reportId("Invalid/"),
373 ReportParams().reportId("Invalid/Invalid/"),
374 ReportParams().reportId("Invalid?")));
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +0200375
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +0100376TEST_P(TestReportInvalidIds, failsToCreateReportWithInvalidName)
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100377{
378 EXPECT_CALL(storageMock, store).Times(0);
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +0100379
380 EXPECT_THROW(makeReport(GetParam()), sdbusplus::exception::SdBusError);
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100381}
382
Krzysztof Grobelnyc8e3a642020-10-23 12:29:16 +0200383class TestReportAllReportTypes :
384 public TestReport,
385 public WithParamInterface<ReportParams>
386{
Wludzik, Jozefb1ff1f62020-10-23 13:20:52 +0200387 public:
Krzysztof Grobelnyc8e3a642020-10-23 12:29:16 +0200388 void SetUp() override
389 {
390 sut = makeReport(GetParam());
391 }
392};
393
Krzysztof Grobelny51497a02021-11-09 14:56:22 +0100394INSTANTIATE_TEST_SUITE_P(
395 _, TestReportAllReportTypes,
396 Values(ReportParams().reportingType(ReportingType::onRequest),
397 ReportParams().reportingType(ReportingType::onChange),
398 ReportParams().reportingType(ReportingType::periodic)));
Krzysztof Grobelnyc8e3a642020-10-23 12:29:16 +0200399
400TEST_P(TestReportAllReportTypes, returnPropertValueOfReportType)
401{
Krzysztof Grobelny51497a02021-11-09 14:56:22 +0100402 EXPECT_THAT(utils::toReportingType(
403 getProperty<std::string>(sut->getPath(), "ReportingType")),
Krzysztof Grobelnyc8e3a642020-10-23 12:29:16 +0200404 Eq(GetParam().reportingType()));
405}
406
Lukasz Kazmierczak7e098e92021-09-16 15:59:56 +0200407TEST_P(TestReportAllReportTypes, updateReadingsCallEnabledPropertyOff)
408{
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100409 clockFake.system.advance(10ms);
Lukasz Kazmierczak7e098e92021-09-16 15:59:56 +0200410
411 setProperty(sut->getPath(), "Enabled", false);
412 sut->updateReadings();
413 const auto [timestamp, readings] =
414 getProperty<Readings>(sut->getPath(), "Readings");
415
416 EXPECT_THAT(getProperty<bool>(sut->getPath(), "Enabled"), Eq(false));
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100417 EXPECT_THAT(Milliseconds{timestamp}, Eq(0ms));
Lukasz Kazmierczak7e098e92021-09-16 15:59:56 +0200418}
419
420TEST_P(TestReportAllReportTypes, updateReadingsCallEnabledPropertyOn)
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +0100421{
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100422 clockFake.system.advance(10ms);
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +0100423
424 sut->updateReadings();
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +0100425 const auto [timestamp, readings] =
426 getProperty<Readings>(sut->getPath(), "Readings");
427
Lukasz Kazmierczak7e098e92021-09-16 15:59:56 +0200428 EXPECT_THAT(getProperty<bool>(sut->getPath(), "Enabled"), Eq(true));
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100429 EXPECT_THAT(Milliseconds{timestamp}, Eq(systemTimestamp + 10ms));
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +0100430}
431
Krzysztof Grobelnyf32f6fe2020-10-30 13:51:58 +0100432class TestReportOnRequestType : public TestReport
433{
434 void SetUp() override
435 {
Krzysztof Grobelny51497a02021-11-09 14:56:22 +0100436 sut =
437 makeReport(ReportParams().reportingType(ReportingType::onRequest));
Krzysztof Grobelnyf32f6fe2020-10-30 13:51:58 +0100438 }
439};
440
441TEST_F(TestReportOnRequestType, updatesReadingTimestamp)
442{
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100443 clockFake.system.advance(10ms);
Krzysztof Grobelnyf32f6fe2020-10-30 13:51:58 +0100444
445 ASSERT_THAT(update(sut->getPath()), Eq(boost::system::errc::success));
446
447 const auto [timestamp, readings] =
448 getProperty<Readings>(sut->getPath(), "Readings");
449
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100450 EXPECT_THAT(Milliseconds{timestamp}, Eq(systemTimestamp + 10ms));
Krzysztof Grobelnyf32f6fe2020-10-30 13:51:58 +0100451}
452
453TEST_F(TestReportOnRequestType, updatesReadingWhenUpdateIsCalled)
454{
455 ASSERT_THAT(update(sut->getPath()), Eq(boost::system::errc::success));
456
457 const auto [timestamp, readings] =
458 getProperty<Readings>(sut->getPath(), "Readings");
459
460 EXPECT_THAT(readings,
461 ElementsAre(std::make_tuple("a"s, "b"s, 17.1, 114u),
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000462 std::make_tuple("aa"s, "bb"s, 42.0, 74u)));
Krzysztof Grobelnyf32f6fe2020-10-30 13:51:58 +0100463}
464
465class TestReportNonOnRequestType :
466 public TestReport,
467 public WithParamInterface<ReportParams>
468{
469 void SetUp() override
470 {
471 sut = makeReport(GetParam());
472 }
473};
474
Krzysztof Grobelny51497a02021-11-09 14:56:22 +0100475INSTANTIATE_TEST_SUITE_P(
476 _, TestReportNonOnRequestType,
477 Values(ReportParams().reportingType(ReportingType::periodic),
478 ReportParams().reportingType(ReportingType::onChange)));
Krzysztof Grobelnyf32f6fe2020-10-30 13:51:58 +0100479
480TEST_P(TestReportNonOnRequestType, readingsAreNotUpdateOnUpdateCall)
481{
482 ASSERT_THAT(update(sut->getPath()), Eq(boost::system::errc::success));
483
484 EXPECT_THAT(getProperty<Readings>(sut->getPath(), "Readings"),
485 Eq(Readings{}));
486}
487
Krzysztof Grobelnyc8e3a642020-10-23 12:29:16 +0200488class TestReportNonPeriodicReport :
489 public TestReport,
490 public WithParamInterface<ReportParams>
491{
Wludzik, Jozefb1ff1f62020-10-23 13:20:52 +0200492 public:
Krzysztof Grobelnyc8e3a642020-10-23 12:29:16 +0200493 void SetUp() override
494 {
495 sut = makeReport(GetParam());
496 }
497};
498
Krzysztof Grobelny51497a02021-11-09 14:56:22 +0100499INSTANTIATE_TEST_SUITE_P(
500 _, TestReportNonPeriodicReport,
501 Values(ReportParams().reportingType(ReportingType::onRequest),
502 ReportParams().reportingType(ReportingType::onChange)));
Krzysztof Grobelnyc8e3a642020-10-23 12:29:16 +0200503
504TEST_P(TestReportNonPeriodicReport, readingsAreNotUpdatedAfterIntervalExpires)
505{
506 DbusEnvironment::sleepFor(ReportManager::minInterval + 1ms);
507
508 EXPECT_THAT(getProperty<Readings>(sut->getPath(), "Readings"),
509 Eq(Readings{}));
510}
511
512class TestReportPeriodicReport : public TestReport
513{
514 void SetUp() override
515 {
Krzysztof Grobelny51497a02021-11-09 14:56:22 +0100516 sut = makeReport(ReportParams().reportingType(ReportingType::periodic));
Krzysztof Grobelnyc8e3a642020-10-23 12:29:16 +0200517 }
518};
519
520TEST_F(TestReportPeriodicReport, readingTimestampIsUpdatedAfterIntervalExpires)
521{
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100522 clockFake.system.advance(10ms);
Krzysztof Grobelnyc8e3a642020-10-23 12:29:16 +0200523 DbusEnvironment::sleepFor(ReportManager::minInterval + 1ms);
524
525 const auto [timestamp, readings] =
526 getProperty<Readings>(sut->getPath(), "Readings");
527
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100528 EXPECT_THAT(Milliseconds{timestamp}, Eq(systemTimestamp + 10ms));
Krzysztof Grobelnyc8e3a642020-10-23 12:29:16 +0200529}
530
531TEST_F(TestReportPeriodicReport, readingsAreUpdatedAfterIntervalExpires)
532{
533 DbusEnvironment::sleepFor(ReportManager::minInterval + 1ms);
534
535 const auto [timestamp, readings] =
536 getProperty<Readings>(sut->getPath(), "Readings");
537
538 EXPECT_THAT(readings,
539 ElementsAre(std::make_tuple("a"s, "b"s, 17.1, 114u),
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000540 std::make_tuple("aa"s, "bb"s, 42.0, 74u)));
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +0200541}
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100542
Szymon Dompke3eb56862021-09-20 15:32:04 +0200543struct ReportUpdatesReportParams
544{
545 ReportParams reportParams;
546 std::vector<ReadingData> expectedReadings;
547 bool expectedEnabled;
548};
549
550class TestReportWithReportUpdatesAndLimit :
551 public TestReport,
552 public WithParamInterface<ReportUpdatesReportParams>
553{
554 void SetUp() override
555 {
556 sut = makeReport(ReportParams(GetParam().reportParams)
Krzysztof Grobelny51497a02021-11-09 14:56:22 +0100557 .reportingType(ReportingType::periodic)
Szymon Dompke3eb56862021-09-20 15:32:04 +0200558 .interval(std::chrono::hours(1000)));
559 }
560};
561
562INSTANTIATE_TEST_SUITE_P(
563 _, TestReportWithReportUpdatesAndLimit,
564 Values(
565 ReportUpdatesReportParams{
Krzysztof Grobelny51497a02021-11-09 14:56:22 +0100566 ReportParams()
567 .reportUpdates(ReportUpdates::appendWrapsWhenFull)
568 .appendLimit(5),
Szymon Dompke3eb56862021-09-20 15:32:04 +0200569 std::vector<ReadingData>{{std::make_tuple("aa"s, "bb"s, 42.0, 74u),
570 std::make_tuple("a"s, "b"s, 17.1, 114u),
571 std::make_tuple("aa"s, "bb"s, 42.0, 74u),
572 std::make_tuple("aa"s, "bb"s, 42.0, 74u),
573 std::make_tuple("a"s, "b"s, 17.1, 114u)}},
574 true},
575 ReportUpdatesReportParams{
Krzysztof Grobelny51497a02021-11-09 14:56:22 +0100576 ReportParams()
577 .reportUpdates(ReportUpdates::appendWrapsWhenFull)
578 .appendLimit(4),
Szymon Dompke3eb56862021-09-20 15:32:04 +0200579 std::vector<ReadingData>{
580 {std::make_tuple("a"s, "b"s, 17.1, 114u),
581 std::make_tuple("aa"s, "bb"s, 42.0, 74u),
582 std::make_tuple("a"s, "b"s, 17.1, 114u),
583 std::make_tuple("aa"s, "bb"s, 42.0, 74u)}},
584 true},
585 ReportUpdatesReportParams{
Krzysztof Grobelny51497a02021-11-09 14:56:22 +0100586 ReportParams()
587 .reportUpdates(ReportUpdates::appendWrapsWhenFull)
588 .appendLimit(0),
Szymon Dompke3eb56862021-09-20 15:32:04 +0200589 std::vector<ReadingData>{}, true},
590 ReportUpdatesReportParams{
Krzysztof Grobelny51497a02021-11-09 14:56:22 +0100591 ReportParams()
592 .reportUpdates(ReportUpdates::appendStopsWhenFull)
593 .appendLimit(10),
Szymon Dompke3eb56862021-09-20 15:32:04 +0200594 std::vector<ReadingData>{
595 {std::make_tuple("a"s, "b"s, 17.1, 114u),
596 std::make_tuple("aa"s, "bb"s, 42.0, 74u),
597 std::make_tuple("a"s, "b"s, 17.1, 114u),
598 std::make_tuple("aa"s, "bb"s, 42.0, 74u),
599 std::make_tuple("a"s, "b"s, 17.1, 114u),
600 std::make_tuple("aa"s, "bb"s, 42.0, 74u),
601 std::make_tuple("a"s, "b"s, 17.1, 114u),
602 std::make_tuple("aa"s, "bb"s, 42.0, 74u)}},
603 true},
604 ReportUpdatesReportParams{
Krzysztof Grobelny51497a02021-11-09 14:56:22 +0100605 ReportParams()
606 .reportUpdates(ReportUpdates::appendStopsWhenFull)
607 .appendLimit(5),
Szymon Dompke3eb56862021-09-20 15:32:04 +0200608 std::vector<ReadingData>{{std::make_tuple("a"s, "b"s, 17.1, 114u),
609 std::make_tuple("aa"s, "bb"s, 42.0, 74u),
610 std::make_tuple("a"s, "b"s, 17.1, 114u),
611 std::make_tuple("aa"s, "bb"s, 42.0, 74u),
612 std::make_tuple("a"s, "b"s, 17.1, 114u)}},
613 false},
614 ReportUpdatesReportParams{
Krzysztof Grobelny51497a02021-11-09 14:56:22 +0100615 ReportParams()
616 .reportUpdates(ReportUpdates::appendStopsWhenFull)
617 .appendLimit(4),
Szymon Dompke3eb56862021-09-20 15:32:04 +0200618 std::vector<ReadingData>{
619 {std::make_tuple("a"s, "b"s, 17.1, 114u),
620 std::make_tuple("aa"s, "bb"s, 42.0, 74u),
621 std::make_tuple("a"s, "b"s, 17.1, 114u),
622 std::make_tuple("aa"s, "bb"s, 42.0, 74u)}},
623 false},
624 ReportUpdatesReportParams{
Krzysztof Grobelny51497a02021-11-09 14:56:22 +0100625 ReportParams()
626 .reportUpdates(ReportUpdates::appendStopsWhenFull)
627 .appendLimit(0),
Szymon Dompke3eb56862021-09-20 15:32:04 +0200628 std::vector<ReadingData>{}, false},
629 ReportUpdatesReportParams{
Krzysztof Grobelny51497a02021-11-09 14:56:22 +0100630 ReportParams()
631 .reportUpdates(ReportUpdates::overwrite)
632 .appendLimit(500),
Szymon Dompke3eb56862021-09-20 15:32:04 +0200633 std::vector<ReadingData>{
634 {std::make_tuple("a"s, "b"s, 17.1, 114u),
635 std::make_tuple("aa"s, "bb"s, 42.0, 74u)}},
636 true},
637 ReportUpdatesReportParams{
Krzysztof Grobelny51497a02021-11-09 14:56:22 +0100638 ReportParams()
639 .reportUpdates(ReportUpdates::overwrite)
640 .appendLimit(1),
Szymon Dompke3eb56862021-09-20 15:32:04 +0200641 std::vector<ReadingData>{
642 {std::make_tuple("a"s, "b"s, 17.1, 114u),
643 std::make_tuple("aa"s, "bb"s, 42.0, 74u)}},
644 true},
645 ReportUpdatesReportParams{
Krzysztof Grobelny51497a02021-11-09 14:56:22 +0100646 ReportParams()
647 .reportUpdates(ReportUpdates::overwrite)
648 .appendLimit(0),
Szymon Dompke3eb56862021-09-20 15:32:04 +0200649 std::vector<ReadingData>{
650 {std::make_tuple("a"s, "b"s, 17.1, 114u),
651 std::make_tuple("aa"s, "bb"s, 42.0, 74u)}},
652 true}));
653
654TEST_P(TestReportWithReportUpdatesAndLimit,
655 readingsAreUpdatedAfterIntervalExpires)
656{
657 for (int i = 0; i < 4; i++)
658 {
659 sut->updateReadings();
660 }
661
662 const auto [timestamp, readings] =
663 getProperty<Readings>(sut->getPath(), "Readings");
664 const auto enabled = getProperty<bool>(sut->getPath(), "Enabled");
665
666 EXPECT_THAT(readings, ElementsAreArray(GetParam().expectedReadings));
667 EXPECT_EQ(enabled, GetParam().expectedEnabled);
668}
669
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100670class TestReportInitialization : public TestReport
671{
672 public:
673 void SetUp() override
674 {}
675
676 void monitorProc(sdbusplus::message::message& msg)
677 {
678 std::string iface;
679 std::vector<std::pair<std::string, std::variant<Readings>>>
680 changed_properties;
681 std::vector<std::string> invalidated_properties;
682
683 msg.read(iface, changed_properties, invalidated_properties);
684
685 if (iface == Report::reportIfaceName)
686 {
687 for (const auto& [name, value] : changed_properties)
688 {
689 if (name == "Readings")
690 {
691 readingsUpdated.Call();
692 }
693 }
694 }
695 }
696
697 void makeMonitor()
698 {
Patrick Williams3a62ee12021-12-03 10:13:25 -0600699 monitor = std::make_unique<sdbusplus::bus::match_t>(
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100700 *DbusEnvironment::getBus(),
701 sdbusplus::bus::match::rules::propertiesChanged(
702 sut->getPath(), Report::reportIfaceName),
703 [this](auto& msg) { monitorProc(msg); });
704 }
705
Patrick Williams3a62ee12021-12-03 10:13:25 -0600706 std::unique_ptr<sdbusplus::bus::match_t> monitor;
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100707 MockFunction<void()> readingsUpdated;
708};
709
Lukasz Kazmierczak7e098e92021-09-16 15:59:56 +0200710TEST_F(TestReportInitialization,
711 metricsAreInitializedWhenEnabledReportConstructed)
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +0100712{
Lukasz Kazmierczak7e098e92021-09-16 15:59:56 +0200713 initMetricMocks(defaultParams.metricParameters());
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +0100714 for (auto& metric : metricMocks)
715 {
Lukasz Kazmierczak7e098e92021-09-16 15:59:56 +0200716 EXPECT_CALL(*metric, initialize()).Times(1);
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +0100717 }
Lukasz Kazmierczak7e098e92021-09-16 15:59:56 +0200718 sut = makeReport(defaultParams.enabled(true));
719}
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +0100720
Lukasz Kazmierczak7e098e92021-09-16 15:59:56 +0200721TEST_F(TestReportInitialization,
722 metricsAreNotInitializedWhenDisabledReportConstructed)
723{
724 initMetricMocks(defaultParams.metricParameters());
725 for (auto& metric : metricMocks)
726 {
727 EXPECT_CALL(*metric, initialize()).Times(0);
728 }
729 sut = makeReport(defaultParams.enabled(false));
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +0100730}
731
Wludzik, Jozefb1ff1f62020-10-23 13:20:52 +0200732TEST_F(TestReportInitialization,
733 emitReadingsUpdateIsTrueReadingsPropertiesChangedSingalEmits)
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100734{
Wludzik, Jozefb1ff1f62020-10-23 13:20:52 +0200735 EXPECT_CALL(readingsUpdated, Call())
736 .WillOnce(
737 InvokeWithoutArgs(DbusEnvironment::setPromise("readingsUpdated")));
738
739 const auto elapsed = DbusEnvironment::measureTime([this] {
Krzysztof Grobelny51497a02021-11-09 14:56:22 +0100740 sut =
741 makeReport(defaultParams.reportingType(ReportingType::periodic)
742 .reportActions({ReportAction::emitsReadingsUpdate}));
Wludzik, Jozefb1ff1f62020-10-23 13:20:52 +0200743 makeMonitor();
744 EXPECT_TRUE(DbusEnvironment::waitForFuture("readingsUpdated"));
745 });
746
747 EXPECT_THAT(elapsed, AllOf(Ge(defaultParams.interval()),
748 Lt(defaultParams.interval() * 2)));
749}
750
751TEST_F(TestReportInitialization,
752 emitReadingsUpdateIsFalseReadingsPropertiesChangesSigalDoesNotEmits)
753{
754 EXPECT_CALL(readingsUpdated, Call()).Times(0);
755
756 sut = makeReport(
Krzysztof Grobelny51497a02021-11-09 14:56:22 +0100757 defaultParams.reportingType(ReportingType::periodic).reportActions({}));
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100758 makeMonitor();
Wludzik, Jozefb1ff1f62020-10-23 13:20:52 +0200759 DbusEnvironment::sleepFor(defaultParams.interval() * 2);
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100760}
Szymon Dompke3eb56862021-09-20 15:32:04 +0200761
762TEST_F(TestReportInitialization, appendLimitDeducedProperly)
763{
764 sut = makeReport(
765 ReportParams().appendLimit(std::numeric_limits<uint64_t>::max()));
766 auto appendLimit = getProperty<uint64_t>(sut->getPath(), "AppendLimit");
767 EXPECT_EQ(appendLimit, 2ull);
768}