blob: 4ad547986491311cf8022497810e44115d3f6f27 [file] [log] [blame]
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +02001#include "dbus_environment.hpp"
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +00002#include "helpers.hpp"
Wludzik, Jozefe2362792020-10-27 17:23:55 +01003#include "mocks/json_storage_mock.hpp"
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +02004#include "mocks/report_factory_mock.hpp"
Wludzik, Jozefe2362792020-10-27 17:23:55 +01005#include "params/report_params.hpp"
6#include "report.hpp"
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +02007#include "report_manager.hpp"
Krzysztof Grobelnye8fc5752021-02-05 14:30:45 +00008#include "utils/conversion.hpp"
Ed Tanous0e7ae5d2021-02-23 14:06:49 -08009#include "utils/set_exception.hpp"
Wludzik, Jozefe2362792020-10-27 17:23:55 +010010#include "utils/transform.hpp"
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +020011
12using namespace testing;
Krzysztof Grobelnye8fc5752021-02-05 14:30:45 +000013using namespace std::string_literals;
Wludzik, Jozefe2362792020-10-27 17:23:55 +010014using namespace std::chrono_literals;
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +020015
16class TestReportManager : public Test
17{
18 public:
Wludzik, Jozefe2362792020-10-27 17:23:55 +010019 ReportParams reportParams;
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +020020
21 std::unique_ptr<ReportFactoryMock> reportFactoryMockPtr =
22 std::make_unique<StrictMock<ReportFactoryMock>>();
23 ReportFactoryMock& reportFactoryMock = *reportFactoryMockPtr;
Wludzik, Jozefe2362792020-10-27 17:23:55 +010024
25 std::unique_ptr<StorageMock> storageMockPtr =
26 std::make_unique<NiceMock<StorageMock>>();
27 StorageMock& storageMock = *storageMockPtr;
28
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +000029 std::unique_ptr<ReportMock> reportMockPtr =
30 std::make_unique<NiceMock<ReportMock>>(reportParams.reportName());
31 ReportMock& reportMock = *reportMockPtr;
32
Wludzik, Jozefe2362792020-10-27 17:23:55 +010033 std::unique_ptr<ReportManager> sut;
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +020034
35 MockFunction<void(std::string)> checkPoint;
36
Wludzik, Jozefe2362792020-10-27 17:23:55 +010037 void SetUp() override
38 {
39 sut = std::make_unique<ReportManager>(std::move(reportFactoryMockPtr),
40 std::move(storageMockPtr),
41 DbusEnvironment::getObjServer());
42 }
43
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +020044 void TearDown() override
45 {
46 DbusEnvironment::synchronizeIoc();
47 }
48
49 std::pair<boost::system::error_code, std::string>
Wludzik, Jozefe2362792020-10-27 17:23:55 +010050 addReport(const ReportParams& params)
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +020051 {
52 std::promise<std::pair<boost::system::error_code, std::string>>
53 addReportPromise;
54 DbusEnvironment::getBus()->async_method_call(
55 [&addReportPromise](boost::system::error_code ec,
56 const std::string& path) {
57 addReportPromise.set_value({ec, path});
58 },
59 DbusEnvironment::serviceName(), ReportManager::reportManagerPath,
Krzysztof Grobelny9f9ff902021-03-05 14:57:53 +000060 ReportManager::reportManagerIfaceName, "AddReport",
Wludzik, Jozefe2362792020-10-27 17:23:55 +010061 params.reportName(), params.reportingType(),
62 params.emitReadingUpdate(), params.logToMetricReportCollection(),
63 static_cast<uint64_t>(params.interval().count()),
64 params.readingParameters());
Krzysztof Grobelnyf32f6fe2020-10-30 13:51:58 +010065 return DbusEnvironment::waitForFuture(addReportPromise.get_future());
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +020066 }
67
68 template <class T>
69 static T getProperty(std::string property)
70 {
Ed Tanous0e7ae5d2021-02-23 14:06:49 -080071 auto propertyPromise = std::promise<T>();
72 auto propertyFuture = propertyPromise.get_future();
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +020073 sdbusplus::asio::getProperty<T>(
74 *DbusEnvironment::getBus(), DbusEnvironment::serviceName(),
75 ReportManager::reportManagerPath,
76 ReportManager::reportManagerIfaceName, property,
Krzysztof Grobelny9f9ff902021-03-05 14:57:53 +000077 [&propertyPromise](boost::system::error_code ec, T t) {
Ed Tanous0e7ae5d2021-02-23 14:06:49 -080078 if (ec)
79 {
Krzysztof Grobelny9f9ff902021-03-05 14:57:53 +000080 utils::setException(propertyPromise, "GetProperty failed");
Ed Tanous0e7ae5d2021-02-23 14:06:49 -080081 return;
82 }
83 propertyPromise.set_value(t);
84 });
85 return DbusEnvironment::waitForFuture(std::move(propertyFuture));
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +020086 }
Karol Niczyj32859b62021-05-19 10:20:46 +020087
88 static std::string prepareReportNameWithLength(size_t length)
89 {
90 std::stringstream reportNameStream;
91 for (size_t i = 0; i < length; ++i)
92 {
93 reportNameStream << "z";
94 }
95 return reportNameStream.str();
96 }
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +020097};
98
99TEST_F(TestReportManager, minInterval)
100{
101 EXPECT_THAT(getProperty<uint64_t>("MinInterval"),
102 Eq(static_cast<uint64_t>(ReportManager::minInterval.count())));
103}
104
105TEST_F(TestReportManager, maxReports)
106{
Wludzik, Jozef503c1582020-12-11 14:48:01 +0100107 EXPECT_THAT(getProperty<size_t>("MaxReports"),
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +0200108 Eq(ReportManager::maxReports));
109}
110
111TEST_F(TestReportManager, addReport)
112{
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +0000113 reportFactoryMock.expectMake(_, reportParams, Ref(*sut), Ref(storageMock))
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +0200114 .WillOnce(Return(ByMove(std::move(reportMockPtr))));
115
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100116 auto [ec, path] = addReport(reportParams);
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +0200117 EXPECT_THAT(ec.value(), Eq(boost::system::errc::success));
118 EXPECT_THAT(path, Eq(reportMock.getPath()));
119}
120
Karol Niczyj32859b62021-05-19 10:20:46 +0200121TEST_F(TestReportManager, addReportWithMaxLengthName)
122{
123 std::string reportName =
124 prepareReportNameWithLength(ReportManager::maxReportNameLength);
125 reportParams.reportName(reportName);
126 reportFactoryMock.expectMake(_, reportParams, Ref(*sut), Ref(storageMock));
127
128 auto [ec, path] = addReport(reportParams);
129
130 EXPECT_THAT(ec.value(), Eq(boost::system::errc::success));
131 EXPECT_THAT(path, Eq("/"s + reportName));
132}
133
134TEST_F(TestReportManager, DISABLED_failToAddReportWithTooLongName)
135{
136 reportFactoryMock.expectMake(_, std::nullopt, Ref(*sut), Ref(storageMock))
137 .Times(0);
138 reportFactoryMock.expectMake(std::nullopt, Ref(*sut), Ref(storageMock), _)
139 .Times(0);
140
141 reportParams.reportName(
142 prepareReportNameWithLength(ReportManager::maxReportNameLength + 1));
143
144 auto [ec, path] = addReport(reportParams);
145
146 EXPECT_THAT(ec.value(), Eq(boost::system::errc::invalid_argument));
147 EXPECT_THAT(path, Eq(std::string()));
148}
149
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100150TEST_F(TestReportManager, DISABLED_failToAddReportTwice)
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +0200151{
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +0000152 reportFactoryMock.expectMake(_, reportParams, Ref(*sut), Ref(storageMock))
153 .WillOnce(Return(ByMove(std::move(reportMockPtr))));
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +0200154
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100155 addReport(reportParams);
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +0200156
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100157 auto [ec, path] = addReport(reportParams);
Karol Niczyj32859b62021-05-19 10:20:46 +0200158
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +0200159 EXPECT_THAT(ec.value(), Eq(boost::system::errc::file_exists));
160 EXPECT_THAT(path, Eq(std::string()));
161}
162
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100163TEST_F(TestReportManager, DISABLED_failToAddReportWithInvalidInterval)
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +0200164{
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +0000165 reportFactoryMock.expectMake(_, std::nullopt, Ref(*sut), Ref(storageMock))
166 .Times(0);
167 reportFactoryMock.expectMake(std::nullopt, Ref(*sut), Ref(storageMock), _)
168 .Times(0);
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +0200169
Wludzik, Jozefbc766b42020-12-08 16:06:22 +0100170 reportParams.reportingType("Periodic");
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100171 reportParams.interval(reportParams.interval() - 1ms);
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +0200172
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100173 auto [ec, path] = addReport(reportParams);
Karol Niczyj32859b62021-05-19 10:20:46 +0200174
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +0200175 EXPECT_THAT(ec.value(), Eq(boost::system::errc::invalid_argument));
176 EXPECT_THAT(path, Eq(std::string()));
177}
178
Wludzik, Jozefbc766b42020-12-08 16:06:22 +0100179TEST_F(TestReportManager, DISABLED_failToAddReportWithInvalidReportingType)
180{
181 reportFactoryMock.expectMake(_, std::nullopt, Ref(*sut), Ref(storageMock))
182 .Times(0);
183 reportFactoryMock.expectMake(std::nullopt, Ref(*sut), Ref(storageMock), _)
184 .Times(0);
185
186 reportParams.reportingType("Invalid");
187
188 auto [ec, path] = addReport(reportParams);
Karol Niczyj32859b62021-05-19 10:20:46 +0200189
Wludzik, Jozefbc766b42020-12-08 16:06:22 +0100190 EXPECT_THAT(ec.value(), Eq(boost::system::errc::invalid_argument));
191 EXPECT_THAT(path, Eq(std::string()));
192}
193
194TEST_F(TestReportManager, DISABLED_failToAddReportWithMoreSensorsThanExpected)
195{
196 reportFactoryMock.expectMake(_, std::nullopt, Ref(*sut), Ref(storageMock))
197 .Times(0);
198 reportFactoryMock.expectMake(std::nullopt, Ref(*sut), Ref(storageMock), _)
199 .Times(0);
200
201 auto readingParams = reportParams.readingParameters();
202 for (size_t i = 0; i < ReportManager::maxReadingParams + 1; i++)
203 {
204 readingParams.push_back(readingParams.front());
205 }
206 reportParams.readingParameters(std::move(readingParams));
207
208 auto [ec, path] = addReport(reportParams);
Karol Niczyj32859b62021-05-19 10:20:46 +0200209
Wludzik, Jozefbc766b42020-12-08 16:06:22 +0100210 EXPECT_THAT(ec.value(), Eq(boost::system::errc::argument_list_too_long));
211 EXPECT_THAT(path, Eq(std::string()));
212}
213
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100214TEST_F(TestReportManager, DISABLED_failToAddReportWhenMaxReportIsReached)
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +0200215{
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +0000216 reportFactoryMock.expectMake(_, std::nullopt, Ref(*sut), Ref(storageMock))
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +0200217 .Times(ReportManager::maxReports);
218
219 for (size_t i = 0; i < ReportManager::maxReports; i++)
220 {
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100221 reportParams.reportName(reportParams.reportName() + std::to_string(i));
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +0200222
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100223 auto [ec, path] = addReport(reportParams);
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +0200224 EXPECT_THAT(ec.value(), Eq(boost::system::errc::success));
225 }
226
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100227 reportParams.reportName(reportParams.reportName() +
228 std::to_string(ReportManager::maxReports));
229 auto [ec, path] = addReport(reportParams);
Karol Niczyj32859b62021-05-19 10:20:46 +0200230
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +0200231 EXPECT_THAT(ec.value(), Eq(boost::system::errc::too_many_files_open));
232 EXPECT_THAT(path, Eq(std::string()));
233}
234
235TEST_F(TestReportManager, removeReport)
236{
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +0200237 {
238 InSequence seq;
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +0000239 reportFactoryMock
240 .expectMake(_, reportParams, Ref(*sut), Ref(storageMock))
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +0200241 .WillOnce(Return(ByMove(std::move(reportMockPtr))));
242 EXPECT_CALL(reportMock, Die());
243 EXPECT_CALL(checkPoint, Call("end"));
244 }
245
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100246 addReport(reportParams);
247 sut->removeReport(&reportMock);
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +0200248 checkPoint.Call("end");
249}
250
251TEST_F(TestReportManager, removingReportThatIsNotInContainerHasNoEffect)
252{
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +0200253 {
254 InSequence seq;
255 EXPECT_CALL(checkPoint, Call("end"));
256 EXPECT_CALL(reportMock, Die());
257 }
258
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100259 sut->removeReport(&reportMock);
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +0200260 checkPoint.Call("end");
261}
262
263TEST_F(TestReportManager, removingSameReportTwiceHasNoSideEffect)
264{
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +0200265 {
266 InSequence seq;
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +0000267 reportFactoryMock
268 .expectMake(_, reportParams, Ref(*sut), Ref(storageMock))
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +0200269 .WillOnce(Return(ByMove(std::move(reportMockPtr))));
270 EXPECT_CALL(reportMock, Die());
271 EXPECT_CALL(checkPoint, Call("end"));
272 }
273
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100274 addReport(reportParams);
275 sut->removeReport(&reportMock);
276 sut->removeReport(&reportMock);
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +0200277 checkPoint.Call("end");
278}
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100279
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +0100280TEST_F(TestReportManager, updateReportCallsUpdateReadingsForExistReport)
281{
282 reportFactoryMock.expectMake(_, reportParams, Ref(*sut), Ref(storageMock))
283 .WillOnce(Return(ByMove(std::move(reportMockPtr))));
284 EXPECT_CALL(reportMock, updateReadings());
285
286 addReport(reportParams);
287 sut->updateReport(reportParams.reportName());
288}
289
290TEST_F(TestReportManager, updateReportDoNothingIfReportDoesNotExist)
291{
292 reportFactoryMock.expectMake(_, reportParams, Ref(*sut), Ref(storageMock))
293 .WillOnce(Return(ByMove(std::move(reportMockPtr))));
294 EXPECT_CALL(reportMock, updateReadings()).Times(0);
295
296 addReport(reportParams);
297 sut->updateReport("NotAReport");
298}
299
Krzysztof Grobelnye8fc5752021-02-05 14:30:45 +0000300class TestReportManagerWithAggregationOperationType :
301 public TestReportManager,
302 public WithParamInterface<OperationType>
303{
304 public:
305 OperationType operationType = GetParam();
306};
307
308INSTANTIATE_TEST_SUITE_P(_, TestReportManagerWithAggregationOperationType,
309 Values(OperationType::single, OperationType::max,
310 OperationType::min, OperationType::avg,
311 OperationType::sum));
312
313TEST_P(TestReportManagerWithAggregationOperationType,
314 addReportWithDifferentOperationTypes)
315{
316 reportParams.readingParameters(
317 {{{sdbusplus::message::object_path(
318 "/xyz/openbmc_project/sensors/power/p1")},
319 utils::enumToString(operationType),
320 "MetricId1",
Krzysztof Grobelny9f9ff902021-03-05 14:57:53 +0000321 "Metadata1"}});
Krzysztof Grobelnye8fc5752021-02-05 14:30:45 +0000322
323 reportFactoryMock.expectMake(_, reportParams, Ref(*sut), Ref(storageMock))
324 .WillOnce(Return(ByMove(std::move(reportMockPtr))));
325
326 auto [ec, path] = addReport(reportParams);
Karol Niczyj32859b62021-05-19 10:20:46 +0200327
Krzysztof Grobelnye8fc5752021-02-05 14:30:45 +0000328 EXPECT_THAT(ec.value(), Eq(boost::system::errc::success));
329 EXPECT_THAT(path, Eq("/"s + reportParams.reportName()));
330}
331
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100332class TestReportManagerStorage : public TestReportManager
333{
334 public:
335 using FilePath = interfaces::JsonStorage::FilePath;
336 using DirectoryPath = interfaces::JsonStorage::DirectoryPath;
337
338 void SetUp() override
339 {
340 ON_CALL(storageMock, list())
341 .WillByDefault(Return(std::vector<FilePath>{FilePath("report1")}));
342 ON_CALL(storageMock, load(FilePath("report1")))
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +0100343 .WillByDefault(InvokeWithoutArgs([this] { return data; }));
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100344 }
345
346 void makeReportManager()
347 {
348 sut = std::make_unique<ReportManager>(std::move(reportFactoryMockPtr),
349 std::move(storageMockPtr),
350 DbusEnvironment::getObjServer());
351 }
352
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +0000353 static std::vector<LabeledMetricParameters>
354 convertToLabeled(const ReadingParameters& params)
355 {
356 return utils::transform(params, [](const auto& item) {
357 return LabeledMetricParameters(
Krzysztof Grobelnye8fc5752021-02-05 14:30:45 +0000358 LabeledSensorParameters("service", std::get<0>(item)),
359 utils::stringToOperationType(std::get<1>(item)),
Krzysztof Grobelny9f9ff902021-03-05 14:57:53 +0000360 std::get<2>(item), std::get<3>(item));
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +0000361 });
362 }
363
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100364 nlohmann::json data = nlohmann::json{
365 {"Version", Report::reportVersion},
366 {"Name", reportParams.reportName()},
367 {"ReportingType", reportParams.reportingType()},
368 {"EmitsReadingsUpdate", reportParams.emitReadingUpdate()},
369 {"LogToMetricReportsCollection",
370 reportParams.logToMetricReportCollection()},
371 {"Interval", reportParams.interval().count()},
372 {"ReadingParameters",
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +0000373 convertToLabeled(reportParams.readingParameters())}};
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100374};
375
376TEST_F(TestReportManagerStorage, reportManagerCtorAddReportFromStorage)
377{
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +0000378 reportFactoryMock.expectMake(
379 reportParams, _, Ref(storageMock),
380 ElementsAreArray(convertToLabeled(reportParams.readingParameters())));
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100381
382 makeReportManager();
383}
384
385TEST_F(TestReportManagerStorage,
386 reportManagerCtorRemoveFileIfVersionDoesNotMatch)
387{
388 data["Version"] = Report::reportVersion - 1;
389
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100390 EXPECT_CALL(storageMock, remove(FilePath("report1")));
391
392 makeReportManager();
393}
394
395TEST_F(TestReportManagerStorage,
396 reportManagerCtorRemoveFileIfIntervalHasWrongType)
397{
398 data["Interval"] = "1000";
399
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100400 EXPECT_CALL(storageMock, remove(FilePath("report1")));
401
402 makeReportManager();
403}