blob: 519606f6c582cb9e29ec0bdc8d831340f9f78d04 [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 }
87};
88
89TEST_F(TestReportManager, minInterval)
90{
91 EXPECT_THAT(getProperty<uint64_t>("MinInterval"),
92 Eq(static_cast<uint64_t>(ReportManager::minInterval.count())));
93}
94
95TEST_F(TestReportManager, maxReports)
96{
Wludzik, Jozef503c1582020-12-11 14:48:01 +010097 EXPECT_THAT(getProperty<size_t>("MaxReports"),
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +020098 Eq(ReportManager::maxReports));
99}
100
101TEST_F(TestReportManager, addReport)
102{
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +0000103 reportFactoryMock.expectMake(_, reportParams, Ref(*sut), Ref(storageMock))
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +0200104 .WillOnce(Return(ByMove(std::move(reportMockPtr))));
105
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100106 auto [ec, path] = addReport(reportParams);
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +0200107 EXPECT_THAT(ec.value(), Eq(boost::system::errc::success));
108 EXPECT_THAT(path, Eq(reportMock.getPath()));
109}
110
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100111TEST_F(TestReportManager, DISABLED_failToAddReportTwice)
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +0200112{
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +0000113 reportFactoryMock.expectMake(_, reportParams, Ref(*sut), Ref(storageMock))
114 .WillOnce(Return(ByMove(std::move(reportMockPtr))));
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +0200115
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100116 addReport(reportParams);
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +0200117
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100118 auto [ec, path] = addReport(reportParams);
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +0200119 EXPECT_THAT(ec.value(), Eq(boost::system::errc::file_exists));
120 EXPECT_THAT(path, Eq(std::string()));
121}
122
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100123TEST_F(TestReportManager, DISABLED_failToAddReportWithInvalidInterval)
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +0200124{
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +0000125 reportFactoryMock.expectMake(_, std::nullopt, Ref(*sut), Ref(storageMock))
126 .Times(0);
127 reportFactoryMock.expectMake(std::nullopt, Ref(*sut), Ref(storageMock), _)
128 .Times(0);
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +0200129
Wludzik, Jozefbc766b42020-12-08 16:06:22 +0100130 reportParams.reportingType("Periodic");
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100131 reportParams.interval(reportParams.interval() - 1ms);
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +0200132
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100133 auto [ec, path] = addReport(reportParams);
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +0200134 EXPECT_THAT(ec.value(), Eq(boost::system::errc::invalid_argument));
135 EXPECT_THAT(path, Eq(std::string()));
136}
137
Wludzik, Jozefbc766b42020-12-08 16:06:22 +0100138TEST_F(TestReportManager, DISABLED_failToAddReportWithInvalidReportingType)
139{
140 reportFactoryMock.expectMake(_, std::nullopt, Ref(*sut), Ref(storageMock))
141 .Times(0);
142 reportFactoryMock.expectMake(std::nullopt, Ref(*sut), Ref(storageMock), _)
143 .Times(0);
144
145 reportParams.reportingType("Invalid");
146
147 auto [ec, path] = addReport(reportParams);
148 EXPECT_THAT(ec.value(), Eq(boost::system::errc::invalid_argument));
149 EXPECT_THAT(path, Eq(std::string()));
150}
151
152TEST_F(TestReportManager, DISABLED_failToAddReportWithMoreSensorsThanExpected)
153{
154 reportFactoryMock.expectMake(_, std::nullopt, Ref(*sut), Ref(storageMock))
155 .Times(0);
156 reportFactoryMock.expectMake(std::nullopt, Ref(*sut), Ref(storageMock), _)
157 .Times(0);
158
159 auto readingParams = reportParams.readingParameters();
160 for (size_t i = 0; i < ReportManager::maxReadingParams + 1; i++)
161 {
162 readingParams.push_back(readingParams.front());
163 }
164 reportParams.readingParameters(std::move(readingParams));
165
166 auto [ec, path] = addReport(reportParams);
167 EXPECT_THAT(ec.value(), Eq(boost::system::errc::argument_list_too_long));
168 EXPECT_THAT(path, Eq(std::string()));
169}
170
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100171TEST_F(TestReportManager, DISABLED_failToAddReportWhenMaxReportIsReached)
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +0200172{
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +0000173 reportFactoryMock.expectMake(_, std::nullopt, Ref(*sut), Ref(storageMock))
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +0200174 .Times(ReportManager::maxReports);
175
176 for (size_t i = 0; i < ReportManager::maxReports; i++)
177 {
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100178 reportParams.reportName(reportParams.reportName() + std::to_string(i));
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +0200179
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100180 auto [ec, path] = addReport(reportParams);
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +0200181 EXPECT_THAT(ec.value(), Eq(boost::system::errc::success));
182 }
183
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100184 reportParams.reportName(reportParams.reportName() +
185 std::to_string(ReportManager::maxReports));
186 auto [ec, path] = addReport(reportParams);
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +0200187 EXPECT_THAT(ec.value(), Eq(boost::system::errc::too_many_files_open));
188 EXPECT_THAT(path, Eq(std::string()));
189}
190
191TEST_F(TestReportManager, removeReport)
192{
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +0200193 {
194 InSequence seq;
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +0000195 reportFactoryMock
196 .expectMake(_, reportParams, Ref(*sut), Ref(storageMock))
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +0200197 .WillOnce(Return(ByMove(std::move(reportMockPtr))));
198 EXPECT_CALL(reportMock, Die());
199 EXPECT_CALL(checkPoint, Call("end"));
200 }
201
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100202 addReport(reportParams);
203 sut->removeReport(&reportMock);
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +0200204 checkPoint.Call("end");
205}
206
207TEST_F(TestReportManager, removingReportThatIsNotInContainerHasNoEffect)
208{
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +0200209 {
210 InSequence seq;
211 EXPECT_CALL(checkPoint, Call("end"));
212 EXPECT_CALL(reportMock, Die());
213 }
214
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100215 sut->removeReport(&reportMock);
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +0200216 checkPoint.Call("end");
217}
218
219TEST_F(TestReportManager, removingSameReportTwiceHasNoSideEffect)
220{
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +0200221 {
222 InSequence seq;
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +0000223 reportFactoryMock
224 .expectMake(_, reportParams, Ref(*sut), Ref(storageMock))
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +0200225 .WillOnce(Return(ByMove(std::move(reportMockPtr))));
226 EXPECT_CALL(reportMock, Die());
227 EXPECT_CALL(checkPoint, Call("end"));
228 }
229
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100230 addReport(reportParams);
231 sut->removeReport(&reportMock);
232 sut->removeReport(&reportMock);
Wludzik, Jozef2f9f9b82020-10-13 09:07:45 +0200233 checkPoint.Call("end");
234}
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100235
Wludzik, Jozefd960e1f2021-01-08 09:25:59 +0100236TEST_F(TestReportManager, updateReportCallsUpdateReadingsForExistReport)
237{
238 reportFactoryMock.expectMake(_, reportParams, Ref(*sut), Ref(storageMock))
239 .WillOnce(Return(ByMove(std::move(reportMockPtr))));
240 EXPECT_CALL(reportMock, updateReadings());
241
242 addReport(reportParams);
243 sut->updateReport(reportParams.reportName());
244}
245
246TEST_F(TestReportManager, updateReportDoNothingIfReportDoesNotExist)
247{
248 reportFactoryMock.expectMake(_, reportParams, Ref(*sut), Ref(storageMock))
249 .WillOnce(Return(ByMove(std::move(reportMockPtr))));
250 EXPECT_CALL(reportMock, updateReadings()).Times(0);
251
252 addReport(reportParams);
253 sut->updateReport("NotAReport");
254}
255
Krzysztof Grobelnye8fc5752021-02-05 14:30:45 +0000256class TestReportManagerWithAggregationOperationType :
257 public TestReportManager,
258 public WithParamInterface<OperationType>
259{
260 public:
261 OperationType operationType = GetParam();
262};
263
264INSTANTIATE_TEST_SUITE_P(_, TestReportManagerWithAggregationOperationType,
265 Values(OperationType::single, OperationType::max,
266 OperationType::min, OperationType::avg,
267 OperationType::sum));
268
269TEST_P(TestReportManagerWithAggregationOperationType,
270 addReportWithDifferentOperationTypes)
271{
272 reportParams.readingParameters(
273 {{{sdbusplus::message::object_path(
274 "/xyz/openbmc_project/sensors/power/p1")},
275 utils::enumToString(operationType),
276 "MetricId1",
Krzysztof Grobelny9f9ff902021-03-05 14:57:53 +0000277 "Metadata1"}});
Krzysztof Grobelnye8fc5752021-02-05 14:30:45 +0000278
279 reportFactoryMock.expectMake(_, reportParams, Ref(*sut), Ref(storageMock))
280 .WillOnce(Return(ByMove(std::move(reportMockPtr))));
281
282 auto [ec, path] = addReport(reportParams);
283 EXPECT_THAT(ec.value(), Eq(boost::system::errc::success));
284 EXPECT_THAT(path, Eq("/"s + reportParams.reportName()));
285}
286
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100287class TestReportManagerStorage : public TestReportManager
288{
289 public:
290 using FilePath = interfaces::JsonStorage::FilePath;
291 using DirectoryPath = interfaces::JsonStorage::DirectoryPath;
292
293 void SetUp() override
294 {
295 ON_CALL(storageMock, list())
296 .WillByDefault(Return(std::vector<FilePath>{FilePath("report1")}));
297 ON_CALL(storageMock, load(FilePath("report1")))
Krzysztof Grobelny6ccfcbf2020-11-04 09:31:36 +0100298 .WillByDefault(InvokeWithoutArgs([this] { return data; }));
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100299 }
300
301 void makeReportManager()
302 {
303 sut = std::make_unique<ReportManager>(std::move(reportFactoryMockPtr),
304 std::move(storageMockPtr),
305 DbusEnvironment::getObjServer());
306 }
307
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +0000308 static std::vector<LabeledMetricParameters>
309 convertToLabeled(const ReadingParameters& params)
310 {
311 return utils::transform(params, [](const auto& item) {
312 return LabeledMetricParameters(
Krzysztof Grobelnye8fc5752021-02-05 14:30:45 +0000313 LabeledSensorParameters("service", std::get<0>(item)),
314 utils::stringToOperationType(std::get<1>(item)),
Krzysztof Grobelny9f9ff902021-03-05 14:57:53 +0000315 std::get<2>(item), std::get<3>(item));
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +0000316 });
317 }
318
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100319 nlohmann::json data = nlohmann::json{
320 {"Version", Report::reportVersion},
321 {"Name", reportParams.reportName()},
322 {"ReportingType", reportParams.reportingType()},
323 {"EmitsReadingsUpdate", reportParams.emitReadingUpdate()},
324 {"LogToMetricReportsCollection",
325 reportParams.logToMetricReportCollection()},
326 {"Interval", reportParams.interval().count()},
327 {"ReadingParameters",
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +0000328 convertToLabeled(reportParams.readingParameters())}};
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100329};
330
331TEST_F(TestReportManagerStorage, reportManagerCtorAddReportFromStorage)
332{
Krzysztof Grobelnyd2238192020-12-02 09:27:28 +0000333 reportFactoryMock.expectMake(
334 reportParams, _, Ref(storageMock),
335 ElementsAreArray(convertToLabeled(reportParams.readingParameters())));
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100336
337 makeReportManager();
338}
339
340TEST_F(TestReportManagerStorage,
341 reportManagerCtorRemoveFileIfVersionDoesNotMatch)
342{
343 data["Version"] = Report::reportVersion - 1;
344
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100345 EXPECT_CALL(storageMock, remove(FilePath("report1")));
346
347 makeReportManager();
348}
349
350TEST_F(TestReportManagerStorage,
351 reportManagerCtorRemoveFileIfIntervalHasWrongType)
352{
353 data["Interval"] = "1000";
354
Wludzik, Jozefe2362792020-10-27 17:23:55 +0100355 EXPECT_CALL(storageMock, remove(FilePath("report1")));
356
357 makeReportManager();
358}