xref: /openbmc/telemetry/tests/src/test_report_manager.cpp (revision 5ade2b1d0ccb71a3de23396dea77c375bedc0362)
1 #include "dbus_environment.hpp"
2 #include "mocks/json_storage_mock.hpp"
3 #include "mocks/report_factory_mock.hpp"
4 #include "params/report_params.hpp"
5 #include "printers.hpp"
6 #include "report.hpp"
7 #include "report_manager.hpp"
8 #include "utils/transform.hpp"
9 
10 using namespace testing;
11 using namespace std::chrono_literals;
12 
13 class TestReportManager : public Test
14 {
15   public:
16     ReportParams reportParams;
17 
18     std::unique_ptr<ReportFactoryMock> reportFactoryMockPtr =
19         std::make_unique<StrictMock<ReportFactoryMock>>();
20     ReportFactoryMock& reportFactoryMock = *reportFactoryMockPtr;
21 
22     std::unique_ptr<StorageMock> storageMockPtr =
23         std::make_unique<NiceMock<StorageMock>>();
24     StorageMock& storageMock = *storageMockPtr;
25 
26     std::unique_ptr<ReportManager> sut;
27 
28     MockFunction<void(std::string)> checkPoint;
29 
30     void SetUp() override
31     {
32         sut = std::make_unique<ReportManager>(std::move(reportFactoryMockPtr),
33                                               std::move(storageMockPtr),
34                                               DbusEnvironment::getObjServer());
35     }
36 
37     void TearDown() override
38     {
39         DbusEnvironment::synchronizeIoc();
40     }
41 
42     std::pair<boost::system::error_code, std::string>
43         addReport(const ReportParams& params)
44     {
45         std::promise<std::pair<boost::system::error_code, std::string>>
46             addReportPromise;
47         DbusEnvironment::getBus()->async_method_call(
48             [&addReportPromise](boost::system::error_code ec,
49                                 const std::string& path) {
50                 addReportPromise.set_value({ec, path});
51             },
52             DbusEnvironment::serviceName(), ReportManager::reportManagerPath,
53             ReportManager::reportManagerIfaceName, "AddReport",
54             params.reportName(), params.reportingType(),
55             params.emitReadingUpdate(), params.logToMetricReportCollection(),
56             static_cast<uint64_t>(params.interval().count()),
57             params.readingParameters());
58         return DbusEnvironment::waitForFuture(addReportPromise.get_future());
59     }
60 
61     template <class T>
62     static T getProperty(std::string property)
63     {
64         std::promise<T> propertyPromise;
65         sdbusplus::asio::getProperty<T>(
66             *DbusEnvironment::getBus(), DbusEnvironment::serviceName(),
67             ReportManager::reportManagerPath,
68             ReportManager::reportManagerIfaceName, property,
69             [&propertyPromise](boost::system::error_code ec) {
70                 EXPECT_THAT(static_cast<bool>(ec), ::testing::Eq(false));
71                 propertyPromise.set_value(T{});
72             },
73             [&propertyPromise](T t) { propertyPromise.set_value(t); });
74         return DbusEnvironment::waitForFuture(propertyPromise.get_future());
75     }
76 };
77 
78 TEST_F(TestReportManager, minInterval)
79 {
80     EXPECT_THAT(getProperty<uint64_t>("MinInterval"),
81                 Eq(static_cast<uint64_t>(ReportManager::minInterval.count())));
82 }
83 
84 TEST_F(TestReportManager, maxReports)
85 {
86     EXPECT_THAT(getProperty<uint32_t>("MaxReports"),
87                 Eq(ReportManager::maxReports));
88 }
89 
90 TEST_F(TestReportManager, addReport)
91 {
92     auto reportMockPtr =
93         std::make_unique<NiceMock<ReportMock>>(reportParams.reportName());
94     auto& reportMock = *reportMockPtr;
95 
96     EXPECT_CALL(reportFactoryMock,
97                 make(_, reportParams.reportName(), reportParams.reportingType(),
98                      reportParams.emitReadingUpdate(),
99                      reportParams.logToMetricReportCollection(),
100                      reportParams.interval(), reportParams.readingParameters(),
101                      Ref(*sut), Ref(storageMock)))
102         .WillOnce(Return(ByMove(std::move(reportMockPtr))));
103 
104     auto [ec, path] = addReport(reportParams);
105     EXPECT_THAT(ec.value(), Eq(boost::system::errc::success));
106     EXPECT_THAT(path, Eq(reportMock.getPath()));
107 }
108 
109 TEST_F(TestReportManager, DISABLED_failToAddReportTwice)
110 {
111     EXPECT_CALL(reportFactoryMock, make(_, _, _, _, _, _, _, _, _));
112 
113     addReport(reportParams);
114 
115     auto [ec, path] = addReport(reportParams);
116     EXPECT_THAT(ec.value(), Eq(boost::system::errc::file_exists));
117     EXPECT_THAT(path, Eq(std::string()));
118 }
119 
120 TEST_F(TestReportManager, DISABLED_failToAddReportWithInvalidInterval)
121 {
122     EXPECT_CALL(reportFactoryMock, make).Times(0);
123 
124     reportParams.interval(reportParams.interval() - 1ms);
125 
126     auto [ec, path] = addReport(reportParams);
127     EXPECT_THAT(ec.value(), Eq(boost::system::errc::invalid_argument));
128     EXPECT_THAT(path, Eq(std::string()));
129 }
130 
131 TEST_F(TestReportManager, DISABLED_failToAddReportWhenMaxReportIsReached)
132 {
133     EXPECT_CALL(reportFactoryMock, make(_, _, _, _, _, _, _, _, _))
134         .Times(ReportManager::maxReports);
135 
136     for (size_t i = 0; i < ReportManager::maxReports; i++)
137     {
138         reportParams.reportName(reportParams.reportName() + std::to_string(i));
139 
140         auto [ec, path] = addReport(reportParams);
141         EXPECT_THAT(ec.value(), Eq(boost::system::errc::success));
142     }
143 
144     reportParams.reportName(reportParams.reportName() +
145                             std::to_string(ReportManager::maxReports));
146     auto [ec, path] = addReport(reportParams);
147     EXPECT_THAT(ec.value(), Eq(boost::system::errc::too_many_files_open));
148     EXPECT_THAT(path, Eq(std::string()));
149 }
150 
151 TEST_F(TestReportManager, removeReport)
152 {
153     auto reportMockPtr =
154         std::make_unique<NiceMock<ReportMock>>(reportParams.reportName());
155     auto& reportMock = *reportMockPtr;
156 
157     {
158         InSequence seq;
159         EXPECT_CALL(reportFactoryMock, make(_, _, _, _, _, _, _, _, _))
160             .WillOnce(Return(ByMove(std::move(reportMockPtr))));
161         EXPECT_CALL(reportMock, Die());
162         EXPECT_CALL(checkPoint, Call("end"));
163     }
164 
165     addReport(reportParams);
166     sut->removeReport(&reportMock);
167     checkPoint.Call("end");
168 }
169 
170 TEST_F(TestReportManager, removingReportThatIsNotInContainerHasNoEffect)
171 {
172     auto reportMockPtr =
173         std::make_unique<NiceMock<ReportMock>>(reportParams.reportName());
174     auto& reportMock = *reportMockPtr;
175 
176     {
177         InSequence seq;
178         EXPECT_CALL(checkPoint, Call("end"));
179         EXPECT_CALL(reportMock, Die());
180     }
181 
182     sut->removeReport(&reportMock);
183     checkPoint.Call("end");
184 }
185 
186 TEST_F(TestReportManager, removingSameReportTwiceHasNoSideEffect)
187 {
188     auto reportMockPtr =
189         std::make_unique<NiceMock<ReportMock>>(reportParams.reportName());
190     auto& reportMock = *reportMockPtr;
191 
192     {
193         InSequence seq;
194         EXPECT_CALL(reportFactoryMock,
195                     make(_, reportParams.reportName(), _, _, _, _, _, _, _))
196             .WillOnce(Return(ByMove(std::move(reportMockPtr))));
197         EXPECT_CALL(reportMock, Die());
198         EXPECT_CALL(checkPoint, Call("end"));
199     }
200 
201     addReport(reportParams);
202     sut->removeReport(&reportMock);
203     sut->removeReport(&reportMock);
204     checkPoint.Call("end");
205 }
206 
207 class TestReportManagerStorage : public TestReportManager
208 {
209   public:
210     using FilePath = interfaces::JsonStorage::FilePath;
211     using DirectoryPath = interfaces::JsonStorage::DirectoryPath;
212 
213     void SetUp() override
214     {
215         ON_CALL(storageMock, list())
216             .WillByDefault(Return(std::vector<FilePath>{FilePath("report1")}));
217         ON_CALL(storageMock, load(FilePath("report1")))
218             .WillByDefault(InvokeWithoutArgs([this] { return data; }));
219     }
220 
221     void makeReportManager()
222     {
223         sut = std::make_unique<ReportManager>(std::move(reportFactoryMockPtr),
224                                               std::move(storageMockPtr),
225                                               DbusEnvironment::getObjServer());
226     }
227 
228     nlohmann::json data = nlohmann::json{
229         {"Version", Report::reportVersion},
230         {"Name", reportParams.reportName()},
231         {"ReportingType", reportParams.reportingType()},
232         {"EmitsReadingsUpdate", reportParams.emitReadingUpdate()},
233         {"LogToMetricReportsCollection",
234          reportParams.logToMetricReportCollection()},
235         {"Interval", reportParams.interval().count()},
236         {"ReadingParameters",
237          utils::transform(reportParams.readingParameters(),
238                           [](const auto& item) {
239                               return LabeledReadingParameter::to_json(item);
240                           })}};
241 };
242 
243 TEST_F(TestReportManagerStorage, reportManagerCtorAddReportFromStorage)
244 {
245     EXPECT_CALL(reportFactoryMock,
246                 make(_, reportParams.reportName(), reportParams.reportingType(),
247                      reportParams.emitReadingUpdate(),
248                      reportParams.logToMetricReportCollection(),
249                      reportParams.interval(), reportParams.readingParameters(),
250                      _, Ref(storageMock)));
251 
252     makeReportManager();
253 }
254 
255 TEST_F(TestReportManagerStorage,
256        reportManagerCtorRemoveFileIfVersionDoesNotMatch)
257 {
258     data["Version"] = Report::reportVersion - 1;
259 
260     EXPECT_CALL(storageMock, remove(FilePath("report1")));
261 
262     makeReportManager();
263 }
264 
265 TEST_F(TestReportManagerStorage,
266        reportManagerCtorRemoveFileIfIntervalHasWrongType)
267 {
268     data["Interval"] = "1000";
269 
270     EXPECT_CALL(storageMock, remove(FilePath("report1")));
271 
272     makeReportManager();
273 }
274