blob: af22166d355d035f99d54b301548ecab2e0b1e5f [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())),
Krzysztof Grobelnye6c417c2022-02-02 17:25:53 +0100283 std::make_pair("AppendLimit",
284 nlohmann::json(ReportParams().appendLimit())),
Krzysztof Grobelnye8fc5752021-02-05 14:30:45 +0000285 std::make_pair(
286 "ReadingParameters",
287 nlohmann::json(
288 {{{tstring::SensorPath::str(),
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000289 {{{tstring::Service::str(), "Service"},
290 {tstring::Path::str(),
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +0100291 "/xyz/openbmc_project/sensors/power/p1"},
292 {tstring::Metadata::str(), "metadata1"}}}},
Krzysztof Grobelnye8fc5752021-02-05 14:30:45 +0000293 {tstring::OperationType::str(), OperationType::single},
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000294 {tstring::Id::str(), "MetricId1"},
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000295 {tstring::CollectionTimeScope::str(),
296 CollectionTimeScope::point},
297 {tstring::CollectionDuration::str(), 0}},
Krzysztof Grobelnye8fc5752021-02-05 14:30:45 +0000298 {{tstring::SensorPath::str(),
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000299 {{{tstring::Service::str(), "Service"},
300 {tstring::Path::str(),
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +0100301 "/xyz/openbmc_project/sensors/power/p2"},
302 {tstring::Metadata::str(), "metadata2"}}}},
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000303 {tstring::OperationType::str(), OperationType::single},
304 {tstring::Id::str(), "MetricId2"},
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000305 {tstring::CollectionTimeScope::str(),
306 CollectionTimeScope::point},
307 {tstring::CollectionDuration::str(), 0}}}))));
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100308
309TEST_P(TestReportStore, settingPersistencyToTrueStoresReport)
310{
311 sut = makeReport(ReportParams());
312
313 {
314 InSequence seq;
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +0100315 EXPECT_CALL(storageMock, remove(to_file_path(sut->getId())));
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100316 EXPECT_CALL(checkPoint, Call());
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +0100317 EXPECT_CALL(storageMock, store(to_file_path(sut->getId()), _))
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100318 .WillOnce(SaveArg<1>(&storedConfiguration));
319 }
320
321 setProperty(sut->getPath(), "Persistency", false);
322 checkPoint.Call();
323 setProperty(sut->getPath(), "Persistency", true);
324
325 const auto& [key, value] = GetParam();
326
327 ASSERT_THAT(storedConfiguration.at(key), Eq(value));
328}
329
330TEST_P(TestReportStore, reportIsSavedToStorageAfterCreated)
331{
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +0100332 EXPECT_CALL(storageMock, store(to_file_path(ReportParams().reportId()), _))
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100333 .WillOnce(SaveArg<1>(&storedConfiguration));
334
335 sut = makeReport(ReportParams());
336
337 const auto& [key, value] = GetParam();
338
339 ASSERT_THAT(storedConfiguration.at(key), Eq(value));
340}
341
Krzysztof Grobelnyc8e3a642020-10-23 12:29:16 +0200342class TestReportValidNames :
343 public TestReport,
344 public WithParamInterface<ReportParams>
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +0200345{
346 public:
Krzysztof Grobelnyc8e3a642020-10-23 12:29:16 +0200347 void SetUp() override
348 {}
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +0200349};
350
Krzysztof Grobelnyc8e3a642020-10-23 12:29:16 +0200351INSTANTIATE_TEST_SUITE_P(
352 ValidNames, TestReportValidNames,
353 Values(ReportParams().reportName("Valid_1"),
354 ReportParams().reportName("Valid_1/Valid_2"),
355 ReportParams().reportName("Valid_1/Valid_2/Valid_3")));
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +0200356
357TEST_P(TestReportValidNames, reportCtorDoesNotThrowOnValidName)
358{
Krzysztof Grobelnyc8e3a642020-10-23 12:29:16 +0200359 EXPECT_NO_THROW(makeReport(GetParam()));
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +0200360}
361
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +0100362class TestReportInvalidIds :
Krzysztof Grobelnyc8e3a642020-10-23 12:29:16 +0200363 public TestReport,
364 public WithParamInterface<ReportParams>
365{
366 public:
367 void SetUp() override
368 {}
369};
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +0200370
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +0100371INSTANTIATE_TEST_SUITE_P(InvalidNames, TestReportInvalidIds,
372 Values(ReportParams().reportId("/"),
373 ReportParams().reportId("/Invalid"),
374 ReportParams().reportId("Invalid/"),
375 ReportParams().reportId("Invalid/Invalid/"),
376 ReportParams().reportId("Invalid?")));
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +0200377
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +0100378TEST_P(TestReportInvalidIds, failsToCreateReportWithInvalidName)
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100379{
380 EXPECT_CALL(storageMock, store).Times(0);
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +0100381
382 EXPECT_THROW(makeReport(GetParam()), sdbusplus::exception::SdBusError);
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100383}
384
Krzysztof Grobelnyc8e3a642020-10-23 12:29:16 +0200385class TestReportAllReportTypes :
386 public TestReport,
387 public WithParamInterface<ReportParams>
388{
Wludzik, Jozefb1ff1f62020-10-23 13:20:52 +0200389 public:
Krzysztof Grobelnyc8e3a642020-10-23 12:29:16 +0200390 void SetUp() override
391 {
392 sut = makeReport(GetParam());
393 }
394};
395
Krzysztof Grobelny51497a02021-11-09 14:56:22 +0100396INSTANTIATE_TEST_SUITE_P(
397 _, TestReportAllReportTypes,
398 Values(ReportParams().reportingType(ReportingType::onRequest),
399 ReportParams().reportingType(ReportingType::onChange),
400 ReportParams().reportingType(ReportingType::periodic)));
Krzysztof Grobelnyc8e3a642020-10-23 12:29:16 +0200401
402TEST_P(TestReportAllReportTypes, returnPropertValueOfReportType)
403{
Krzysztof Grobelny51497a02021-11-09 14:56:22 +0100404 EXPECT_THAT(utils::toReportingType(
405 getProperty<std::string>(sut->getPath(), "ReportingType")),
Krzysztof Grobelnyc8e3a642020-10-23 12:29:16 +0200406 Eq(GetParam().reportingType()));
407}
408
Lukasz Kazmierczak7e098e92021-09-16 15:59:56 +0200409TEST_P(TestReportAllReportTypes, updateReadingsCallEnabledPropertyOff)
410{
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100411 clockFake.system.advance(10ms);
Lukasz Kazmierczak7e098e92021-09-16 15:59:56 +0200412
413 setProperty(sut->getPath(), "Enabled", false);
414 sut->updateReadings();
415 const auto [timestamp, readings] =
416 getProperty<Readings>(sut->getPath(), "Readings");
417
418 EXPECT_THAT(getProperty<bool>(sut->getPath(), "Enabled"), Eq(false));
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100419 EXPECT_THAT(Milliseconds{timestamp}, Eq(0ms));
Lukasz Kazmierczak7e098e92021-09-16 15:59:56 +0200420}
421
422TEST_P(TestReportAllReportTypes, updateReadingsCallEnabledPropertyOn)
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +0100423{
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100424 clockFake.system.advance(10ms);
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +0100425
426 sut->updateReadings();
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +0100427 const auto [timestamp, readings] =
428 getProperty<Readings>(sut->getPath(), "Readings");
429
Lukasz Kazmierczak7e098e92021-09-16 15:59:56 +0200430 EXPECT_THAT(getProperty<bool>(sut->getPath(), "Enabled"), Eq(true));
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100431 EXPECT_THAT(Milliseconds{timestamp}, Eq(systemTimestamp + 10ms));
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +0100432}
433
Krzysztof Grobelnyf32f6fe2020-10-30 13:51:58 +0100434class TestReportOnRequestType : public TestReport
435{
436 void SetUp() override
437 {
Krzysztof Grobelny51497a02021-11-09 14:56:22 +0100438 sut =
439 makeReport(ReportParams().reportingType(ReportingType::onRequest));
Krzysztof Grobelnyf32f6fe2020-10-30 13:51:58 +0100440 }
441};
442
443TEST_F(TestReportOnRequestType, updatesReadingTimestamp)
444{
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100445 clockFake.system.advance(10ms);
Krzysztof Grobelnyf32f6fe2020-10-30 13:51:58 +0100446
447 ASSERT_THAT(update(sut->getPath()), Eq(boost::system::errc::success));
448
449 const auto [timestamp, readings] =
450 getProperty<Readings>(sut->getPath(), "Readings");
451
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100452 EXPECT_THAT(Milliseconds{timestamp}, Eq(systemTimestamp + 10ms));
Krzysztof Grobelnyf32f6fe2020-10-30 13:51:58 +0100453}
454
455TEST_F(TestReportOnRequestType, updatesReadingWhenUpdateIsCalled)
456{
457 ASSERT_THAT(update(sut->getPath()), Eq(boost::system::errc::success));
458
459 const auto [timestamp, readings] =
460 getProperty<Readings>(sut->getPath(), "Readings");
461
462 EXPECT_THAT(readings,
463 ElementsAre(std::make_tuple("a"s, "b"s, 17.1, 114u),
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000464 std::make_tuple("aa"s, "bb"s, 42.0, 74u)));
Krzysztof Grobelnyf32f6fe2020-10-30 13:51:58 +0100465}
466
467class TestReportNonOnRequestType :
468 public TestReport,
469 public WithParamInterface<ReportParams>
470{
471 void SetUp() override
472 {
473 sut = makeReport(GetParam());
474 }
475};
476
Krzysztof Grobelny51497a02021-11-09 14:56:22 +0100477INSTANTIATE_TEST_SUITE_P(
478 _, TestReportNonOnRequestType,
479 Values(ReportParams().reportingType(ReportingType::periodic),
480 ReportParams().reportingType(ReportingType::onChange)));
Krzysztof Grobelnyf32f6fe2020-10-30 13:51:58 +0100481
482TEST_P(TestReportNonOnRequestType, readingsAreNotUpdateOnUpdateCall)
483{
484 ASSERT_THAT(update(sut->getPath()), Eq(boost::system::errc::success));
485
486 EXPECT_THAT(getProperty<Readings>(sut->getPath(), "Readings"),
487 Eq(Readings{}));
488}
489
Krzysztof Grobelnyc8e3a642020-10-23 12:29:16 +0200490class TestReportNonPeriodicReport :
491 public TestReport,
492 public WithParamInterface<ReportParams>
493{
Wludzik, Jozefb1ff1f62020-10-23 13:20:52 +0200494 public:
Krzysztof Grobelnyc8e3a642020-10-23 12:29:16 +0200495 void SetUp() override
496 {
497 sut = makeReport(GetParam());
498 }
499};
500
Krzysztof Grobelny51497a02021-11-09 14:56:22 +0100501INSTANTIATE_TEST_SUITE_P(
502 _, TestReportNonPeriodicReport,
503 Values(ReportParams().reportingType(ReportingType::onRequest),
504 ReportParams().reportingType(ReportingType::onChange)));
Krzysztof Grobelnyc8e3a642020-10-23 12:29:16 +0200505
506TEST_P(TestReportNonPeriodicReport, readingsAreNotUpdatedAfterIntervalExpires)
507{
508 DbusEnvironment::sleepFor(ReportManager::minInterval + 1ms);
509
510 EXPECT_THAT(getProperty<Readings>(sut->getPath(), "Readings"),
511 Eq(Readings{}));
512}
513
514class TestReportPeriodicReport : public TestReport
515{
516 void SetUp() override
517 {
Krzysztof Grobelny51497a02021-11-09 14:56:22 +0100518 sut = makeReport(ReportParams().reportingType(ReportingType::periodic));
Krzysztof Grobelnyc8e3a642020-10-23 12:29:16 +0200519 }
520};
521
522TEST_F(TestReportPeriodicReport, readingTimestampIsUpdatedAfterIntervalExpires)
523{
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100524 clockFake.system.advance(10ms);
Krzysztof Grobelnyc8e3a642020-10-23 12:29:16 +0200525 DbusEnvironment::sleepFor(ReportManager::minInterval + 1ms);
526
527 const auto [timestamp, readings] =
528 getProperty<Readings>(sut->getPath(), "Readings");
529
Krzysztof Grobelny51f0fd52021-12-28 16:32:08 +0100530 EXPECT_THAT(Milliseconds{timestamp}, Eq(systemTimestamp + 10ms));
Krzysztof Grobelnyc8e3a642020-10-23 12:29:16 +0200531}
532
533TEST_F(TestReportPeriodicReport, readingsAreUpdatedAfterIntervalExpires)
534{
535 DbusEnvironment::sleepFor(ReportManager::minInterval + 1ms);
536
537 const auto [timestamp, readings] =
538 getProperty<Readings>(sut->getPath(), "Readings");
539
540 EXPECT_THAT(readings,
541 ElementsAre(std::make_tuple("a"s, "b"s, 17.1, 114u),
Krzysztof Grobelnydcc4e192021-03-08 09:09:34 +0000542 std::make_tuple("aa"s, "bb"s, 42.0, 74u)));
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +0200543}
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100544
Szymon Dompke3eb56862021-09-20 15:32:04 +0200545struct ReportUpdatesReportParams
546{
547 ReportParams reportParams;
548 std::vector<ReadingData> expectedReadings;
549 bool expectedEnabled;
550};
551
552class TestReportWithReportUpdatesAndLimit :
553 public TestReport,
554 public WithParamInterface<ReportUpdatesReportParams>
555{
556 void SetUp() override
557 {
558 sut = makeReport(ReportParams(GetParam().reportParams)
Krzysztof Grobelny51497a02021-11-09 14:56:22 +0100559 .reportingType(ReportingType::periodic)
Szymon Dompke3eb56862021-09-20 15:32:04 +0200560 .interval(std::chrono::hours(1000)));
561 }
562};
563
564INSTANTIATE_TEST_SUITE_P(
565 _, TestReportWithReportUpdatesAndLimit,
566 Values(
567 ReportUpdatesReportParams{
Krzysztof Grobelny51497a02021-11-09 14:56:22 +0100568 ReportParams()
569 .reportUpdates(ReportUpdates::appendWrapsWhenFull)
570 .appendLimit(5),
Szymon Dompke3eb56862021-09-20 15:32:04 +0200571 std::vector<ReadingData>{{std::make_tuple("aa"s, "bb"s, 42.0, 74u),
572 std::make_tuple("a"s, "b"s, 17.1, 114u),
573 std::make_tuple("aa"s, "bb"s, 42.0, 74u),
574 std::make_tuple("aa"s, "bb"s, 42.0, 74u),
575 std::make_tuple("a"s, "b"s, 17.1, 114u)}},
576 true},
577 ReportUpdatesReportParams{
Krzysztof Grobelny51497a02021-11-09 14:56:22 +0100578 ReportParams()
579 .reportUpdates(ReportUpdates::appendWrapsWhenFull)
580 .appendLimit(4),
Szymon Dompke3eb56862021-09-20 15:32:04 +0200581 std::vector<ReadingData>{
582 {std::make_tuple("a"s, "b"s, 17.1, 114u),
583 std::make_tuple("aa"s, "bb"s, 42.0, 74u),
584 std::make_tuple("a"s, "b"s, 17.1, 114u),
585 std::make_tuple("aa"s, "bb"s, 42.0, 74u)}},
586 true},
587 ReportUpdatesReportParams{
Krzysztof Grobelny51497a02021-11-09 14:56:22 +0100588 ReportParams()
589 .reportUpdates(ReportUpdates::appendWrapsWhenFull)
590 .appendLimit(0),
Szymon Dompke3eb56862021-09-20 15:32:04 +0200591 std::vector<ReadingData>{}, true},
592 ReportUpdatesReportParams{
Krzysztof Grobelny51497a02021-11-09 14:56:22 +0100593 ReportParams()
594 .reportUpdates(ReportUpdates::appendStopsWhenFull)
595 .appendLimit(10),
Szymon Dompke3eb56862021-09-20 15:32:04 +0200596 std::vector<ReadingData>{
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 std::make_tuple("a"s, "b"s, 17.1, 114u),
604 std::make_tuple("aa"s, "bb"s, 42.0, 74u)}},
605 true},
606 ReportUpdatesReportParams{
Krzysztof Grobelny51497a02021-11-09 14:56:22 +0100607 ReportParams()
608 .reportUpdates(ReportUpdates::appendStopsWhenFull)
609 .appendLimit(5),
Szymon Dompke3eb56862021-09-20 15:32:04 +0200610 std::vector<ReadingData>{{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 std::make_tuple("aa"s, "bb"s, 42.0, 74u),
614 std::make_tuple("a"s, "b"s, 17.1, 114u)}},
615 false},
616 ReportUpdatesReportParams{
Krzysztof Grobelny51497a02021-11-09 14:56:22 +0100617 ReportParams()
618 .reportUpdates(ReportUpdates::appendStopsWhenFull)
619 .appendLimit(4),
Szymon Dompke3eb56862021-09-20 15:32:04 +0200620 std::vector<ReadingData>{
621 {std::make_tuple("a"s, "b"s, 17.1, 114u),
622 std::make_tuple("aa"s, "bb"s, 42.0, 74u),
623 std::make_tuple("a"s, "b"s, 17.1, 114u),
624 std::make_tuple("aa"s, "bb"s, 42.0, 74u)}},
625 false},
626 ReportUpdatesReportParams{
Krzysztof Grobelny51497a02021-11-09 14:56:22 +0100627 ReportParams()
628 .reportUpdates(ReportUpdates::appendStopsWhenFull)
629 .appendLimit(0),
Szymon Dompke3eb56862021-09-20 15:32:04 +0200630 std::vector<ReadingData>{}, false},
631 ReportUpdatesReportParams{
Krzysztof Grobelny51497a02021-11-09 14:56:22 +0100632 ReportParams()
633 .reportUpdates(ReportUpdates::overwrite)
634 .appendLimit(500),
Szymon Dompke3eb56862021-09-20 15:32:04 +0200635 std::vector<ReadingData>{
636 {std::make_tuple("a"s, "b"s, 17.1, 114u),
637 std::make_tuple("aa"s, "bb"s, 42.0, 74u)}},
638 true},
639 ReportUpdatesReportParams{
Krzysztof Grobelny51497a02021-11-09 14:56:22 +0100640 ReportParams()
641 .reportUpdates(ReportUpdates::overwrite)
642 .appendLimit(1),
Szymon Dompke3eb56862021-09-20 15:32:04 +0200643 std::vector<ReadingData>{
644 {std::make_tuple("a"s, "b"s, 17.1, 114u),
645 std::make_tuple("aa"s, "bb"s, 42.0, 74u)}},
646 true},
647 ReportUpdatesReportParams{
Krzysztof Grobelny51497a02021-11-09 14:56:22 +0100648 ReportParams()
649 .reportUpdates(ReportUpdates::overwrite)
650 .appendLimit(0),
Szymon Dompke3eb56862021-09-20 15:32:04 +0200651 std::vector<ReadingData>{
652 {std::make_tuple("a"s, "b"s, 17.1, 114u),
653 std::make_tuple("aa"s, "bb"s, 42.0, 74u)}},
654 true}));
655
656TEST_P(TestReportWithReportUpdatesAndLimit,
657 readingsAreUpdatedAfterIntervalExpires)
658{
659 for (int i = 0; i < 4; i++)
660 {
661 sut->updateReadings();
662 }
663
664 const auto [timestamp, readings] =
665 getProperty<Readings>(sut->getPath(), "Readings");
666 const auto enabled = getProperty<bool>(sut->getPath(), "Enabled");
667
668 EXPECT_THAT(readings, ElementsAreArray(GetParam().expectedReadings));
669 EXPECT_EQ(enabled, GetParam().expectedEnabled);
670}
671
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100672class TestReportInitialization : public TestReport
673{
674 public:
675 void SetUp() override
676 {}
677
678 void monitorProc(sdbusplus::message::message& msg)
679 {
680 std::string iface;
681 std::vector<std::pair<std::string, std::variant<Readings>>>
682 changed_properties;
683 std::vector<std::string> invalidated_properties;
684
685 msg.read(iface, changed_properties, invalidated_properties);
686
687 if (iface == Report::reportIfaceName)
688 {
689 for (const auto& [name, value] : changed_properties)
690 {
691 if (name == "Readings")
692 {
693 readingsUpdated.Call();
694 }
695 }
696 }
697 }
698
699 void makeMonitor()
700 {
Patrick Williams3a62ee12021-12-03 10:13:25 -0600701 monitor = std::make_unique<sdbusplus::bus::match_t>(
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100702 *DbusEnvironment::getBus(),
703 sdbusplus::bus::match::rules::propertiesChanged(
704 sut->getPath(), Report::reportIfaceName),
705 [this](auto& msg) { monitorProc(msg); });
706 }
707
Patrick Williams3a62ee12021-12-03 10:13:25 -0600708 std::unique_ptr<sdbusplus::bus::match_t> monitor;
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100709 MockFunction<void()> readingsUpdated;
710};
711
Lukasz Kazmierczak7e098e92021-09-16 15:59:56 +0200712TEST_F(TestReportInitialization,
713 metricsAreInitializedWhenEnabledReportConstructed)
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +0100714{
Lukasz Kazmierczak7e098e92021-09-16 15:59:56 +0200715 initMetricMocks(defaultParams.metricParameters());
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +0100716 for (auto& metric : metricMocks)
717 {
Lukasz Kazmierczak7e098e92021-09-16 15:59:56 +0200718 EXPECT_CALL(*metric, initialize()).Times(1);
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +0100719 }
Lukasz Kazmierczak7e098e92021-09-16 15:59:56 +0200720 sut = makeReport(defaultParams.enabled(true));
721}
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +0100722
Lukasz Kazmierczak7e098e92021-09-16 15:59:56 +0200723TEST_F(TestReportInitialization,
724 metricsAreNotInitializedWhenDisabledReportConstructed)
725{
726 initMetricMocks(defaultParams.metricParameters());
727 for (auto& metric : metricMocks)
728 {
729 EXPECT_CALL(*metric, initialize()).Times(0);
730 }
731 sut = makeReport(defaultParams.enabled(false));
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +0100732}
733
Wludzik, Jozefb1ff1f62020-10-23 13:20:52 +0200734TEST_F(TestReportInitialization,
735 emitReadingsUpdateIsTrueReadingsPropertiesChangedSingalEmits)
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100736{
Wludzik, Jozefb1ff1f62020-10-23 13:20:52 +0200737 EXPECT_CALL(readingsUpdated, Call())
738 .WillOnce(
739 InvokeWithoutArgs(DbusEnvironment::setPromise("readingsUpdated")));
740
741 const auto elapsed = DbusEnvironment::measureTime([this] {
Krzysztof Grobelny51497a02021-11-09 14:56:22 +0100742 sut =
743 makeReport(defaultParams.reportingType(ReportingType::periodic)
744 .reportActions({ReportAction::emitsReadingsUpdate}));
Wludzik, Jozefb1ff1f62020-10-23 13:20:52 +0200745 makeMonitor();
746 EXPECT_TRUE(DbusEnvironment::waitForFuture("readingsUpdated"));
747 });
748
749 EXPECT_THAT(elapsed, AllOf(Ge(defaultParams.interval()),
750 Lt(defaultParams.interval() * 2)));
751}
752
753TEST_F(TestReportInitialization,
754 emitReadingsUpdateIsFalseReadingsPropertiesChangesSigalDoesNotEmits)
755{
756 EXPECT_CALL(readingsUpdated, Call()).Times(0);
757
758 sut = makeReport(
Krzysztof Grobelny51497a02021-11-09 14:56:22 +0100759 defaultParams.reportingType(ReportingType::periodic).reportActions({}));
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100760 makeMonitor();
Wludzik, Jozefb1ff1f62020-10-23 13:20:52 +0200761 DbusEnvironment::sleepFor(defaultParams.interval() * 2);
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100762}
Szymon Dompke3eb56862021-09-20 15:32:04 +0200763
764TEST_F(TestReportInitialization, appendLimitDeducedProperly)
765{
766 sut = makeReport(
767 ReportParams().appendLimit(std::numeric_limits<uint64_t>::max()));
768 auto appendLimit = getProperty<uint64_t>(sut->getPath(), "AppendLimit");
769 EXPECT_EQ(appendLimit, 2ull);
770}
Krzysztof Grobelnye6c417c2022-02-02 17:25:53 +0100771
772TEST_F(TestReportInitialization, appendLimitSetToUintMaxIsStoredCorrectly)
773{
774 nlohmann::json storedConfiguration;
775
776 EXPECT_CALL(storageMock, store(to_file_path(ReportParams().reportId()), _))
777 .WillOnce(SaveArg<1>(&storedConfiguration));
778
779 sut = makeReport(
780 ReportParams().appendLimit(std::numeric_limits<uint64_t>::max()));
781
782 ASSERT_THAT(storedConfiguration.at("AppendLimit"),
783 Eq(std::numeric_limits<uint64_t>::max()));
784}