xref: /openbmc/telemetry/tests/src/test_report_manager.cpp (revision 2f9f9b875ad61666b1308a94fa700ae6e9d5ed1e)
1 #include "dbus_environment.hpp"
2 #include "mocks/report_factory_mock.hpp"
3 #include "report_manager.hpp"
4 
5 using namespace testing;
6 
7 class TestReportManager : public Test
8 {
9   public:
10     std::string defaultReportName = "TestReport";
11     std::string defaultReportType = "Periodic";
12     bool defaultEmitReadingSignal = true;
13     bool defaultLogToMetricReportCollection = true;
14     uint64_t defaultInterval = ReportManager::minInterval.count();
15     ReadingParameters defaultReadingParams = {};
16 
17     std::unique_ptr<ReportFactoryMock> reportFactoryMockPtr =
18         std::make_unique<StrictMock<ReportFactoryMock>>();
19     ReportFactoryMock& reportFactoryMock = *reportFactoryMockPtr;
20     ReportManager sut = ReportManager(std::move(reportFactoryMockPtr),
21                                       DbusEnvironment::getObjServer());
22 
23     MockFunction<void(std::string)> checkPoint;
24 
25     void TearDown() override
26     {
27         DbusEnvironment::synchronizeIoc();
28     }
29 
30     std::pair<boost::system::error_code, std::string>
31         addReport(const std::string& reportName,
32                   uint64_t interval = ReportManager::minInterval.count())
33     {
34         std::promise<std::pair<boost::system::error_code, std::string>>
35             addReportPromise;
36         DbusEnvironment::getBus()->async_method_call(
37             [&addReportPromise](boost::system::error_code ec,
38                                 const std::string& path) {
39                 addReportPromise.set_value({ec, path});
40             },
41             DbusEnvironment::serviceName(), ReportManager::reportManagerPath,
42             ReportManager::reportManagerIfaceName, "AddReport", reportName,
43             defaultReportType, defaultEmitReadingSignal,
44             defaultLogToMetricReportCollection, interval, defaultReadingParams);
45         return DbusEnvironment::waitForFuture(addReportPromise.get_future())
46             .value_or(std::pair<boost::system::error_code, std::string>{});
47     }
48 
49     template <class T>
50     static T getProperty(std::string property)
51     {
52         std::promise<T> propertyPromise;
53         sdbusplus::asio::getProperty<T>(
54             *DbusEnvironment::getBus(), DbusEnvironment::serviceName(),
55             ReportManager::reportManagerPath,
56             ReportManager::reportManagerIfaceName, property,
57             [&propertyPromise](boost::system::error_code ec) {
58                 EXPECT_THAT(static_cast<bool>(ec), ::testing::Eq(false));
59                 propertyPromise.set_value(T{});
60             },
61             [&propertyPromise](T t) { propertyPromise.set_value(t); });
62         return DbusEnvironment::waitForFuture(propertyPromise.get_future())
63             .value_or(T{});
64     }
65 };
66 
67 TEST_F(TestReportManager, minInterval)
68 {
69     EXPECT_THAT(getProperty<uint64_t>("MinInterval"),
70                 Eq(static_cast<uint64_t>(ReportManager::minInterval.count())));
71 }
72 
73 TEST_F(TestReportManager, maxReports)
74 {
75     EXPECT_THAT(getProperty<uint32_t>("MaxReports"),
76                 Eq(ReportManager::maxReports));
77 }
78 
79 TEST_F(TestReportManager, addReport)
80 {
81     auto reportMockPtr =
82         std::make_unique<NiceMock<ReportMock>>(defaultReportName);
83     auto& reportMock = *reportMockPtr;
84 
85     EXPECT_CALL(reportFactoryMock,
86                 make(defaultReportName, defaultReportType,
87                      defaultEmitReadingSignal,
88                      defaultLogToMetricReportCollection,
89                      std::chrono::milliseconds{defaultInterval},
90                      defaultReadingParams, Ref(sut)))
91         .WillOnce(Return(ByMove(std::move(reportMockPtr))));
92 
93     auto [ec, path] = addReport(defaultReportName);
94     EXPECT_THAT(ec.value(), Eq(boost::system::errc::success));
95     EXPECT_THAT(path, Eq(reportMock.getPath()));
96 }
97 
98 TEST_F(TestReportManager, failToAddReportTwice)
99 {
100     EXPECT_CALL(reportFactoryMock, make(_, _, _, _, _, _, _));
101 
102     addReport(defaultReportName);
103 
104     auto [ec, path] = addReport(defaultReportName);
105     EXPECT_THAT(ec.value(), Eq(boost::system::errc::file_exists));
106     EXPECT_THAT(path, Eq(std::string()));
107 }
108 
109 TEST_F(TestReportManager, failToAddReportWithInvalidInterval)
110 {
111     EXPECT_CALL(reportFactoryMock, make(_, _, _, _, _, _, _)).Times(0);
112 
113     uint64_t interval = defaultInterval - 1;
114 
115     auto [ec, path] = addReport(defaultReportName, interval);
116     EXPECT_THAT(ec.value(), Eq(boost::system::errc::invalid_argument));
117     EXPECT_THAT(path, Eq(std::string()));
118 }
119 
120 TEST_F(TestReportManager, failToAddReportWhenMaxReportIsReached)
121 {
122     EXPECT_CALL(reportFactoryMock, make(_, _, _, _, _, _, _))
123         .Times(ReportManager::maxReports);
124 
125     for (size_t i = 0; i < ReportManager::maxReports; i++)
126     {
127         std::string reportName = defaultReportName + std::to_string(i);
128 
129         auto [ec, path] = addReport(reportName);
130         EXPECT_THAT(ec.value(), Eq(boost::system::errc::success));
131     }
132 
133     std::string reportName =
134         defaultReportName + std::to_string(ReportManager::maxReports);
135     auto [ec, path] = addReport(reportName);
136     EXPECT_THAT(ec.value(), Eq(boost::system::errc::too_many_files_open));
137     EXPECT_THAT(path, Eq(std::string()));
138 }
139 
140 TEST_F(TestReportManager, removeReport)
141 {
142     auto reportMockPtr =
143         std::make_unique<NiceMock<ReportMock>>(defaultReportName);
144     auto& reportMock = *reportMockPtr;
145 
146     {
147         InSequence seq;
148         EXPECT_CALL(reportFactoryMock, make(_, _, _, _, _, _, _))
149             .WillOnce(Return(ByMove(std::move(reportMockPtr))));
150         EXPECT_CALL(reportMock, Die());
151         EXPECT_CALL(checkPoint, Call("end"));
152     }
153 
154     addReport(defaultReportName);
155     sut.removeReport(&reportMock);
156     checkPoint.Call("end");
157 }
158 
159 TEST_F(TestReportManager, removingReportThatIsNotInContainerHasNoEffect)
160 {
161     auto reportMockPtr =
162         std::make_unique<NiceMock<ReportMock>>(defaultReportName);
163     auto& reportMock = *reportMockPtr;
164 
165     {
166         InSequence seq;
167         EXPECT_CALL(checkPoint, Call("end"));
168         EXPECT_CALL(reportMock, Die());
169     }
170 
171     sut.removeReport(&reportMock);
172     checkPoint.Call("end");
173 }
174 
175 TEST_F(TestReportManager, removingSameReportTwiceHasNoSideEffect)
176 {
177     auto reportMockPtr =
178         std::make_unique<NiceMock<ReportMock>>(defaultReportName);
179     auto& reportMock = *reportMockPtr;
180 
181     {
182         InSequence seq;
183         EXPECT_CALL(reportFactoryMock,
184                     make(defaultReportName, _, _, _, _, _, _))
185             .WillOnce(Return(ByMove(std::move(reportMockPtr))));
186         EXPECT_CALL(reportMock, Die());
187         EXPECT_CALL(checkPoint, Call("end"));
188     }
189 
190     addReport(defaultReportName);
191     sut.removeReport(&reportMock);
192     sut.removeReport(&reportMock);
193     checkPoint.Call("end");
194 }
195