xref: /openbmc/telemetry/tests/src/test_report.cpp (revision c8e3a64a)
1 #include "dbus_environment.hpp"
2 #include "mocks/metric_mock.hpp"
3 #include "mocks/report_manager_mock.hpp"
4 #include "params/report_params.hpp"
5 #include "report.hpp"
6 #include "report_manager.hpp"
7 #include "utils/conv_container.hpp"
8 
9 #include <sdbusplus/exception.hpp>
10 
11 using namespace testing;
12 using namespace std::literals::string_literals;
13 using namespace std::chrono_literals;
14 
15 class TestReport : public Test
16 {
17   public:
18     bool defaultEmitReadingSignal = true;
19     bool defaultLogToMetricReportCollection = true;
20     uint64_t defaultInterval = ReportManager::minInterval.count();
21     ReadingParameters defaultReadingParams = {};
22 
23     std::unique_ptr<ReportManagerMock> reportManagerMock =
24         std::make_unique<StrictMock<ReportManagerMock>>();
25     std::vector<std::shared_ptr<MetricMock>> metricMocks = {
26         std::make_shared<NiceMock<MetricMock>>(),
27         std::make_shared<NiceMock<MetricMock>>(),
28         std::make_shared<NiceMock<MetricMock>>()};
29     std::unique_ptr<Report> sut;
30 
31     void SetUp() override
32     {
33         sut = makeReport(ReportParams());
34     }
35 
36     std::unique_ptr<Report> makeReport(const ReportParams& params)
37     {
38         return std::make_unique<Report>(
39             DbusEnvironment::getIoc(), DbusEnvironment::getObjServer(),
40             params.reportName(), params.reportingType(),
41             defaultEmitReadingSignal, defaultLogToMetricReportCollection,
42             std::chrono::milliseconds(defaultInterval), defaultReadingParams,
43             *reportManagerMock,
44             utils::convContainer<std::shared_ptr<interfaces::Metric>>(
45                 metricMocks));
46     }
47 
48     template <class T>
49     static T getProperty(const std::string& path, const std::string& property)
50     {
51         std::promise<T> propertyPromise;
52         sdbusplus::asio::getProperty<T>(
53             *DbusEnvironment::getBus(), DbusEnvironment::serviceName(), path,
54             Report::reportIfaceName, property,
55             [&propertyPromise](boost::system::error_code ec) {
56                 EXPECT_THAT(static_cast<bool>(ec), ::testing::Eq(false));
57                 propertyPromise.set_value(T{});
58             },
59             [&propertyPromise](T t) { propertyPromise.set_value(t); });
60         return DbusEnvironment::waitForFuture(propertyPromise.get_future())
61             .value_or(T{});
62     }
63 
64     template <class T>
65     static boost::system::error_code setProperty(const std::string& path,
66                                                  const std::string& property,
67                                                  const T& newValue)
68     {
69         std::promise<boost::system::error_code> setPromise;
70         sdbusplus::asio::setProperty(
71             *DbusEnvironment::getBus(), DbusEnvironment::serviceName(), path,
72             Report::reportIfaceName, property, std::move(newValue),
73             [&setPromise](boost::system::error_code ec) {
74                 setPromise.set_value(ec);
75             },
76             [&setPromise]() {
77                 setPromise.set_value(boost::system::error_code{});
78             });
79         return DbusEnvironment::waitForFuture(setPromise.get_future())
80             .value_or(boost::system::error_code{});
81     }
82 
83     boost::system::error_code deleteReport(const std::string& path)
84     {
85         std::promise<boost::system::error_code> deleteReportPromise;
86         DbusEnvironment::getBus()->async_method_call(
87             [&deleteReportPromise](boost::system::error_code ec) {
88                 deleteReportPromise.set_value(ec);
89             },
90             DbusEnvironment::serviceName(), path, Report::deleteIfaceName,
91             "Delete");
92         return DbusEnvironment::waitForFuture(deleteReportPromise.get_future())
93             .value_or(boost::system::error_code{});
94     }
95 };
96 
97 TEST_F(TestReport, verifyIfPropertiesHaveValidValue)
98 {
99     EXPECT_THAT(getProperty<uint64_t>(sut->getPath(), "Interval"),
100                 Eq(defaultInterval));
101     EXPECT_THAT(getProperty<bool>(sut->getPath(), "Persistency"), Eq(false));
102     EXPECT_THAT(getProperty<bool>(sut->getPath(), "EmitsReadingsUpdate"),
103                 Eq(defaultEmitReadingSignal));
104     EXPECT_THAT(
105         getProperty<bool>(sut->getPath(), "LogToMetricReportsCollection"),
106         Eq(defaultLogToMetricReportCollection));
107     EXPECT_THAT(
108         getProperty<ReadingParameters>(sut->getPath(), "ReadingParameters"),
109         Eq(defaultReadingParams));
110 }
111 
112 TEST_F(TestReport, readingsAreInitialyEmpty)
113 {
114     EXPECT_THAT(getProperty<Readings>(sut->getPath(), "Readings"),
115                 Eq(Readings{}));
116 }
117 
118 TEST_F(TestReport, setIntervalWithValidValue)
119 {
120     uint64_t newValue = defaultInterval + 1;
121     EXPECT_THAT(setProperty(sut->getPath(), "Interval", newValue).value(),
122                 Eq(boost::system::errc::success));
123     EXPECT_THAT(getProperty<uint64_t>(sut->getPath(), "Interval"),
124                 Eq(newValue));
125 }
126 
127 TEST_F(TestReport, settingIntervalWithInvalidValueDoesNotChangeProperty)
128 {
129     uint64_t newValue = defaultInterval - 1;
130     EXPECT_THAT(setProperty(sut->getPath(), "Interval", newValue).value(),
131                 Eq(boost::system::errc::success));
132     EXPECT_THAT(getProperty<uint64_t>(sut->getPath(), "Interval"),
133                 Eq(defaultInterval));
134 }
135 
136 TEST_F(TestReport, deleteReport)
137 {
138     EXPECT_CALL(*reportManagerMock, removeReport(sut.get()));
139     auto ec = deleteReport(sut->getPath());
140     EXPECT_THAT(ec, Eq(boost::system::errc::success));
141 }
142 
143 TEST_F(TestReport, deletingNonExistingReportReturnInvalidRequestDescriptor)
144 {
145     auto ec = deleteReport(Report::reportDir + "NonExisting"s);
146     EXPECT_THAT(ec.value(), Eq(EBADR));
147 }
148 
149 class TestReportValidNames :
150     public TestReport,
151     public WithParamInterface<ReportParams>
152 {
153   public:
154     void SetUp() override
155     {}
156 };
157 
158 INSTANTIATE_TEST_SUITE_P(
159     ValidNames, TestReportValidNames,
160     Values(ReportParams().reportName("Valid_1"),
161            ReportParams().reportName("Valid_1/Valid_2"),
162            ReportParams().reportName("Valid_1/Valid_2/Valid_3")));
163 
164 TEST_P(TestReportValidNames, reportCtorDoesNotThrowOnValidName)
165 {
166     EXPECT_NO_THROW(makeReport(GetParam()));
167 }
168 
169 class TestReportInvalidNames :
170     public TestReport,
171     public WithParamInterface<ReportParams>
172 {
173   public:
174     void SetUp() override
175     {}
176 };
177 
178 INSTANTIATE_TEST_SUITE_P(InvalidNames, TestReportInvalidNames,
179                          Values(ReportParams().reportName("/"),
180                                 ReportParams().reportName("/Invalid"),
181                                 ReportParams().reportName("Invalid/"),
182                                 ReportParams().reportName("Invalid/Invalid/"),
183                                 ReportParams().reportName("Invalid?")));
184 
185 TEST_P(TestReportInvalidNames, reportCtorThrowOnInvalidName)
186 {
187     EXPECT_THROW(makeReport(GetParam()), sdbusplus::exception::SdBusError);
188 }
189 
190 class TestReportAllReportTypes :
191     public TestReport,
192     public WithParamInterface<ReportParams>
193 {
194     void SetUp() override
195     {
196         sut = makeReport(GetParam());
197     }
198 };
199 
200 INSTANTIATE_TEST_SUITE_P(_, TestReportAllReportTypes,
201                          Values(ReportParams().reportingType("OnRequest"),
202                                 ReportParams().reportingType("OnChange"),
203                                 ReportParams().reportingType("Periodic")));
204 
205 TEST_P(TestReportAllReportTypes, returnPropertValueOfReportType)
206 {
207     EXPECT_THAT(getProperty<std::string>(sut->getPath(), "ReportingType"),
208                 Eq(GetParam().reportingType()));
209 }
210 
211 class TestReportNonPeriodicReport :
212     public TestReport,
213     public WithParamInterface<ReportParams>
214 {
215     void SetUp() override
216     {
217         sut = makeReport(GetParam());
218     }
219 };
220 
221 INSTANTIATE_TEST_SUITE_P(_, TestReportNonPeriodicReport,
222                          Values(ReportParams().reportingType("OnRequest"),
223                                 ReportParams().reportingType("OnChange")));
224 
225 TEST_P(TestReportNonPeriodicReport, readingsAreNotUpdatedAfterIntervalExpires)
226 {
227     DbusEnvironment::sleepFor(ReportManager::minInterval + 1ms);
228 
229     EXPECT_THAT(getProperty<Readings>(sut->getPath(), "Readings"),
230                 Eq(Readings{}));
231 }
232 
233 class TestReportPeriodicReport : public TestReport
234 {
235     void SetUp() override
236     {
237         sut = makeReport(ReportParams().reportingType("Periodic"));
238 
239         ASSERT_THAT(metricMocks, SizeIs(Ge(2)));
240         ON_CALL(*metricMocks[0], getReadings())
241             .WillByDefault(ReturnRefOfCopy(std::vector<MetricValue>(
242                 {MetricValue{"a", "b", 17.1, 114},
243                  MetricValue{"aaa", "bbb", 21.7, 100}})));
244         ON_CALL(*metricMocks[1], getReadings())
245             .WillByDefault(ReturnRefOfCopy(
246                 std::vector<MetricValue>({MetricValue{"aa", "bb", 42.0, 74}})));
247     }
248 };
249 
250 TEST_F(TestReportPeriodicReport, readingTimestampIsUpdatedAfterIntervalExpires)
251 {
252     const uint64_t expectedTime = std::time(0);
253     DbusEnvironment::sleepFor(ReportManager::minInterval + 1ms);
254 
255     const auto [timestamp, readings] =
256         getProperty<Readings>(sut->getPath(), "Readings");
257 
258     EXPECT_THAT(timestamp, Ge(expectedTime));
259 }
260 
261 TEST_F(TestReportPeriodicReport, readingsAreUpdatedAfterIntervalExpires)
262 {
263     DbusEnvironment::sleepFor(ReportManager::minInterval + 1ms);
264 
265     const auto [timestamp, readings] =
266         getProperty<Readings>(sut->getPath(), "Readings");
267 
268     EXPECT_THAT(readings,
269                 ElementsAre(std::make_tuple("a"s, "b"s, 17.1, 114u),
270                             std::make_tuple("aaa"s, "bbb"s, 21.7, 100u),
271                             std::make_tuple("aa"s, "bb"s, 42.0, 74u)));
272 }
273