blob: 58d0df1c8c110cb7cfeef15caa83c1d17cd18395 [file] [log] [blame]
Wludzik, Jozef76833cb2020-12-21 14:42:41 +01001#include "dbus_environment.hpp"
2#include "helpers.hpp"
Cezary Zwolaka4e67612021-02-18 13:16:16 +01003#include "mocks/json_storage_mock.hpp"
Wludzik, Jozef76833cb2020-12-21 14:42:41 +01004#include "mocks/trigger_factory_mock.hpp"
5#include "mocks/trigger_mock.hpp"
6#include "params/trigger_params.hpp"
Cezary Zwolak4416fce2021-03-17 03:21:06 +01007#include "trigger.hpp"
Wludzik, Jozef76833cb2020-12-21 14:42:41 +01008#include "trigger_manager.hpp"
Cezary Zwolak4416fce2021-03-17 03:21:06 +01009#include "utils/conversion_trigger.hpp"
10#include "utils/transform.hpp"
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010011
12using namespace testing;
Szymon Dompke1cdd7e42022-06-08 14:43:13 +020013using sdbusplus::message::object_path;
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010014
15class TestTriggerManager : public Test
16{
17 public:
18 std::pair<boost::system::error_code, std::string>
19 addTrigger(const TriggerParams& params)
20 {
Cezary Zwolak4416fce2021-03-17 03:21:06 +010021 const auto sensorInfos =
22 utils::fromLabeledSensorsInfo(params.sensors());
23
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010024 std::promise<std::pair<boost::system::error_code, std::string>>
25 addTriggerPromise;
26 DbusEnvironment::getBus()->async_method_call(
27 [&addTriggerPromise](boost::system::error_code ec,
28 const std::string& path) {
29 addTriggerPromise.set_value({ec, path});
30 },
31 DbusEnvironment::serviceName(), TriggerManager::triggerManagerPath,
Szymon Dompkee28aa532021-10-27 12:33:12 +020032 TriggerManager::triggerManagerIfaceName, "AddTrigger", params.id(),
Szymon Dompke94f71c52021-12-10 07:16:33 +010033 params.name(),
34 utils::transform(
35 params.triggerActions(),
36 [](const auto& action) { return actionToString(action); }),
Szymon Dompke1cdd7e42022-06-08 14:43:13 +020037 sensorInfos, params.reports(),
Cezary Zwolak4416fce2021-03-17 03:21:06 +010038 std::visit(utils::FromLabeledThresholdParamConversion(),
39 params.thresholdParams()));
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010040 return DbusEnvironment::waitForFuture(addTriggerPromise.get_future());
41 }
42
Cezary Zwolak4416fce2021-03-17 03:21:06 +010043 std::unique_ptr<TriggerManager> makeTriggerManager()
44 {
45 return std::make_unique<TriggerManager>(
46 std::move(triggerFactoryMockPtr), std::move(storageMockPtr),
47 DbusEnvironment::getObjServer());
48 }
49
50 void SetUp() override
51 {
52 sut = makeTriggerManager();
53 }
54
Cezary Zwolaka4e67612021-02-18 13:16:16 +010055 std::unique_ptr<StorageMock> storageMockPtr =
56 std::make_unique<NiceMock<StorageMock>>();
57 StorageMock& storageMock = *storageMockPtr;
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010058 std::unique_ptr<TriggerFactoryMock> triggerFactoryMockPtr =
59 std::make_unique<NiceMock<TriggerFactoryMock>>();
60 TriggerFactoryMock& triggerFactoryMock = *triggerFactoryMockPtr;
61 std::unique_ptr<TriggerMock> triggerMockPtr =
Szymon Dompkee28aa532021-10-27 12:33:12 +020062 std::make_unique<NiceMock<TriggerMock>>(TriggerParams().id());
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010063 TriggerMock& triggerMock = *triggerMockPtr;
Cezary Zwolak4416fce2021-03-17 03:21:06 +010064 std::unique_ptr<TriggerManager> sut;
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010065 MockFunction<void(std::string)> checkPoint;
66};
67
68TEST_F(TestTriggerManager, addTrigger)
69{
Cezary Zwolak4416fce2021-03-17 03:21:06 +010070 triggerFactoryMock.expectMake(TriggerParams(), Ref(*sut), Ref(storageMock))
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010071 .WillOnce(Return(ByMove(std::move(triggerMockPtr))));
72
Cezary Zwolak4416fce2021-03-17 03:21:06 +010073 auto [ec, path] = addTrigger(TriggerParams());
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010074 EXPECT_THAT(ec.value(), Eq(boost::system::errc::success));
75 EXPECT_THAT(path, Eq(triggerMock.getPath()));
76}
77
Szymon Dompkef763c9e2021-03-12 09:19:22 +010078TEST_F(TestTriggerManager, addTriggerWithDiscreteThresholds)
79{
80 TriggerParams triggerParamsDiscrete;
Cezary Zwolak4416fce2021-03-17 03:21:06 +010081 auto thresholds = std::vector<discrete::LabeledThresholdParam>{
Szymon Dompke9f346792021-07-14 21:07:11 +020082 {"discrete_threshold1", discrete::Severity::ok, 10, "11.0"},
83 {"discrete_threshold2", discrete::Severity::warning, 10, "12.0"},
84 {"discrete_threshold3", discrete::Severity::critical, 10, "13.0"}};
Szymon Dompkef763c9e2021-03-12 09:19:22 +010085
Szymon Dompke20013012021-07-23 09:54:20 +020086 triggerParamsDiscrete.thresholdParams(thresholds);
Szymon Dompkef763c9e2021-03-12 09:19:22 +010087
88 auto [ec, path] = addTrigger(triggerParamsDiscrete);
89 EXPECT_THAT(ec.value(), Eq(boost::system::errc::success));
90 EXPECT_THAT(path, Eq(triggerMock.getPath()));
91}
92
93TEST_F(TestTriggerManager, addDiscreteTriggerWithoutThresholds)
94{
95 TriggerParams triggerParamsDiscrete;
Cezary Zwolak4416fce2021-03-17 03:21:06 +010096 auto thresholds = std::vector<discrete::LabeledThresholdParam>();
Szymon Dompkef763c9e2021-03-12 09:19:22 +010097
Szymon Dompke20013012021-07-23 09:54:20 +020098 triggerParamsDiscrete.thresholdParams(thresholds);
Szymon Dompkef763c9e2021-03-12 09:19:22 +010099
100 auto [ec, path] = addTrigger(triggerParamsDiscrete);
101 EXPECT_THAT(ec.value(), Eq(boost::system::errc::success));
102 EXPECT_THAT(path, Eq(triggerMock.getPath()));
103}
104
Wludzik, Jozef1477fe62021-01-02 11:56:10 +0100105TEST_F(TestTriggerManager, DISABLED_failToAddTriggerTwice)
Wludzik, Jozef76833cb2020-12-21 14:42:41 +0100106{
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100107 triggerFactoryMock.expectMake(TriggerParams(), Ref(*sut), Ref(storageMock))
Wludzik, Jozef76833cb2020-12-21 14:42:41 +0100108 .WillOnce(Return(ByMove(std::move(triggerMockPtr))));
109
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100110 addTrigger(TriggerParams());
Wludzik, Jozef76833cb2020-12-21 14:42:41 +0100111
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100112 auto [ec, path] = addTrigger(TriggerParams());
Wludzik, Jozef76833cb2020-12-21 14:42:41 +0100113 EXPECT_THAT(ec.value(), Eq(boost::system::errc::file_exists));
114 EXPECT_THAT(path, Eq(std::string()));
115}
116
Szymon Dompkee28aa532021-10-27 12:33:12 +0200117TEST_F(TestTriggerManager, DISABLED_failToAddTriggerWithInvalidId)
118{
119 triggerFactoryMock.expectMake(std::nullopt, Ref(*sut), Ref(storageMock))
120 .Times(0);
121
122 auto [ec, path] = addTrigger(TriggerParams().id("not valid?"));
123 EXPECT_THAT(ec.value(), Eq(boost::system::errc::invalid_argument));
124 EXPECT_THAT(path, Eq(std::string()));
125}
126
Szymon Dompkeb4ef22e2022-02-07 15:15:12 +0100127TEST_F(TestTriggerManager, DISABLED_failToAddTriggerWithDuplicatesInReportsIds)
128{
129 triggerFactoryMock.expectMake(std::nullopt, Ref(*sut), Ref(storageMock))
130 .Times(0);
131
132 auto [ec, path] = addTrigger(
133 TriggerParams().reportIds({"trigger1", "trigger2", "trigger1"}));
134 EXPECT_THAT(ec.value(), Eq(boost::system::errc::invalid_argument));
135 EXPECT_THAT(path, Eq(std::string()));
136}
137
Szymon Dompke1cdd7e42022-06-08 14:43:13 +0200138TEST_F(TestTriggerManager, addTriggerWithProperReportPaths)
139{
140 auto [ec, path] = addTrigger(TriggerParams().reports(
141 {object_path("/xyz/openbmc_project/Telemetry/Reports/MyReport"),
142 object_path(
143 "/xyz/openbmc_project/Telemetry/Reports/MyPrefix/MyReport")}));
144 EXPECT_THAT(ec.value(), Eq(boost::system::errc::success));
145 EXPECT_THAT(path, Eq(triggerMock.getPath()));
146}
147
148TEST_F(TestTriggerManager, DISABLED_failToAddTriggerWithBadReportsPath)
149{
150 triggerFactoryMock.expectMake(std::nullopt, Ref(*sut), Ref(storageMock))
151 .Times(0);
152
153 auto [ec, path] = addTrigger(TriggerParams().reports(
154 {object_path("/xyz/openbmc_project/Telemetry/NotReports/MyReport")}));
155 EXPECT_THAT(ec.value(), Eq(boost::system::errc::invalid_argument));
156 EXPECT_THAT(path, Eq(std::string()));
157}
158
159TEST_F(TestTriggerManager, DISABLED_failToAddTriggerWithTooManyReportPrefixes)
160{
161 triggerFactoryMock.expectMake(std::nullopt, Ref(*sut), Ref(storageMock))
162 .Times(0);
163
164 auto [ec, path] = addTrigger(TriggerParams().reports({object_path(
165 "/xyz/openbmc_project/Telemetry/Reports/P1/P2/MyReport")}));
166 EXPECT_THAT(ec.value(), Eq(boost::system::errc::invalid_argument));
167 EXPECT_THAT(path, Eq(std::string()));
168}
169
Szymon Dompkee28aa532021-10-27 12:33:12 +0200170TEST_F(TestTriggerManager, addTriggerWithoutIdAndName)
171{
172 triggerFactoryMock
173 .expectMake(TriggerParams()
174 .id(TriggerManager::triggerNameDefault)
175 .name(TriggerManager::triggerNameDefault),
176 Ref(*sut), Ref(storageMock))
177 .WillOnce(Return(ByMove(std::move(triggerMockPtr))));
178
179 auto [ec, path] = addTrigger(TriggerParams().id("").name(""));
180 EXPECT_THAT(ec.value(), Eq(boost::system::errc::success));
181 EXPECT_THAT(path, Not(Eq("")));
182}
183
184TEST_F(TestTriggerManager, addTriggerWithPrefixId)
185{
186 triggerFactoryMock
187 .expectMake(TriggerParams()
188 .id("TelemetryService/HackyName")
189 .name("Hacky/Name!@#$"),
190 Ref(*sut), Ref(storageMock))
191 .WillOnce(Return(ByMove(std::move(triggerMockPtr))));
192
193 auto [ec, path] = addTrigger(
194 TriggerParams().id("TelemetryService/").name("Hacky/Name!@#$"));
195 EXPECT_THAT(ec.value(), Eq(boost::system::errc::success));
196 EXPECT_THAT(path, Not(Eq("")));
197}
198
199TEST_F(TestTriggerManager, addTriggerWithoutIdTwice)
200{
201 addTrigger(TriggerParams().id(""));
202
203 auto [ec, path] = addTrigger(TriggerParams().id(""));
204 EXPECT_THAT(ec.value(), Eq(boost::system::errc::success));
205 EXPECT_THAT(path, Not(Eq("")));
206}
207
208TEST_F(TestTriggerManager, addTriggerWithoutIdAndWithLongNameTwice)
209{
210 addTrigger(TriggerParams().id("").name(
211 std::string(2 * TriggerManager::maxTriggerIdLength, 'z')));
212
213 auto [ec, path] = addTrigger(TriggerParams().id("").name(
214 std::string(2 * TriggerManager::maxTriggerIdLength, 'z')));
215 EXPECT_THAT(ec.value(), Eq(boost::system::errc::success));
216 EXPECT_THAT(path, Not(Eq("")));
217}
218
219TEST_F(TestTriggerManager, addTriggerWithMaxLengthId)
220{
221 auto triggerId = std::string(TriggerManager::maxTriggerIdLength, 'z');
222 auto triggerParams = TriggerParams().id(triggerId);
223
224 triggerFactoryMock.expectMake(triggerParams, Ref(*sut), Ref(storageMock))
225 .WillOnce(Return(ByMove(std::move(triggerMockPtr))));
226
227 auto [ec, path] = addTrigger(triggerParams);
228
229 EXPECT_THAT(ec.value(), Eq(boost::system::errc::success));
230 EXPECT_THAT(path, Eq(triggerMock.getPath()));
231}
232
233TEST_F(TestTriggerManager, DISABLED_failToAddTriggerWithTooLongId)
234{
235 auto triggerId = std::string(TriggerManager::maxTriggerIdLength + 1, 'z');
236 auto triggerParams = TriggerParams().id(triggerId);
237
238 triggerFactoryMock.expectMake(std::nullopt, Ref(*sut), Ref(storageMock))
239 .Times(0);
240
241 auto [ec, path] = addTrigger(triggerParams);
242
243 EXPECT_THAT(ec.value(), Eq(boost::system::errc::invalid_argument));
244 EXPECT_THAT(path, Eq(std::string()));
245}
246
Wludzik, Jozef1477fe62021-01-02 11:56:10 +0100247TEST_F(TestTriggerManager, DISABLED_failToAddTriggerWhenMaxTriggerIsReached)
Wludzik, Jozef76833cb2020-12-21 14:42:41 +0100248{
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100249 auto triggerParams = TriggerParams();
250
Cezary Zwolaka4e67612021-02-18 13:16:16 +0100251 triggerFactoryMock.expectMake(std::nullopt, Ref(*sut), Ref(storageMock))
Wludzik, Jozef76833cb2020-12-21 14:42:41 +0100252 .Times(TriggerManager::maxTriggers);
253
254 for (size_t i = 0; i < TriggerManager::maxTriggers; i++)
255 {
Szymon Dompkee28aa532021-10-27 12:33:12 +0200256 triggerParams.id(TriggerParams().id() + std::to_string(i));
Wludzik, Jozef76833cb2020-12-21 14:42:41 +0100257
258 auto [ec, path] = addTrigger(triggerParams);
259 EXPECT_THAT(ec.value(), Eq(boost::system::errc::success));
260 }
261
Szymon Dompkee28aa532021-10-27 12:33:12 +0200262 triggerParams.id(TriggerParams().id() +
263 std::to_string(TriggerManager::maxTriggers));
Wludzik, Jozef76833cb2020-12-21 14:42:41 +0100264 auto [ec, path] = addTrigger(triggerParams);
265 EXPECT_THAT(ec.value(), Eq(boost::system::errc::too_many_files_open));
266 EXPECT_THAT(path, Eq(std::string()));
267}
268
269TEST_F(TestTriggerManager, removeTrigger)
270{
271 {
272 InSequence seq;
Cezary Zwolaka4e67612021-02-18 13:16:16 +0100273 triggerFactoryMock
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100274 .expectMake(TriggerParams(), Ref(*sut), Ref(storageMock))
Wludzik, Jozef76833cb2020-12-21 14:42:41 +0100275 .WillOnce(Return(ByMove(std::move(triggerMockPtr))));
276 EXPECT_CALL(triggerMock, Die());
277 EXPECT_CALL(checkPoint, Call("end"));
278 }
279
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100280 addTrigger(TriggerParams());
Wludzik, Jozef76833cb2020-12-21 14:42:41 +0100281 sut->removeTrigger(&triggerMock);
282 checkPoint.Call("end");
283}
284
285TEST_F(TestTriggerManager, removingTriggerThatIsNotInContainerHasNoEffect)
286{
287 {
288 InSequence seq;
289 EXPECT_CALL(checkPoint, Call("end"));
290 EXPECT_CALL(triggerMock, Die());
291 }
292
293 sut->removeTrigger(&triggerMock);
294 checkPoint.Call("end");
295}
296
297TEST_F(TestTriggerManager, removingSameTriggerTwiceHasNoSideEffect)
298{
299 {
300 InSequence seq;
Cezary Zwolaka4e67612021-02-18 13:16:16 +0100301 triggerFactoryMock
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100302 .expectMake(TriggerParams(), Ref(*sut), Ref(storageMock))
Wludzik, Jozef76833cb2020-12-21 14:42:41 +0100303 .WillOnce(Return(ByMove(std::move(triggerMockPtr))));
304 EXPECT_CALL(triggerMock, Die());
305 EXPECT_CALL(checkPoint, Call("end"));
306 }
307
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100308 addTrigger(TriggerParams());
Wludzik, Jozef76833cb2020-12-21 14:42:41 +0100309 sut->removeTrigger(&triggerMock);
310 sut->removeTrigger(&triggerMock);
311 checkPoint.Call("end");
312}
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100313class TestTriggerManagerStorage : public TestTriggerManager
314{
315 public:
316 using FilePath = interfaces::JsonStorage::FilePath;
317 using DirectoryPath = interfaces::JsonStorage::DirectoryPath;
318
319 void SetUp() override
320 {
321 ON_CALL(storageMock, list())
322 .WillByDefault(Return(std::vector<FilePath>{
323 {FilePath("trigger1")}, {FilePath("trigger2")}}));
324
325 ON_CALL(storageMock, load(FilePath("trigger1")))
326 .WillByDefault(InvokeWithoutArgs([this] { return data1; }));
327
Szymon Dompkee28aa532021-10-27 12:33:12 +0200328 data2["Id"] = "Trigger2";
329 data2["Name"] = "Second Trigger";
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100330 ON_CALL(storageMock, load(FilePath("trigger2")))
331 .WillByDefault(InvokeWithoutArgs([this] { return data2; }));
332 }
333
334 nlohmann::json data1 = nlohmann::json{
335 {"Version", Trigger::triggerVersion},
Szymon Dompkee28aa532021-10-27 12:33:12 +0200336 {"Id", TriggerParams().id()},
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100337 {"Name", TriggerParams().name()},
338 {"ThresholdParamsDiscriminator",
339 TriggerParams().thresholdParams().index()},
Szymon Dompke94f71c52021-12-10 07:16:33 +0100340 {"TriggerActions", utils::transform(TriggerParams().triggerActions(),
341 [](const auto& action) {
342 return actionToString(action);
343 })},
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100344 {"ThresholdParams", utils::labeledThresholdParamsToJson(
345 TriggerParams().thresholdParams())},
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +0100346 {"ReportIds", TriggerParams().reportIds()},
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100347 {"Sensors", TriggerParams().sensors()}};
348
349 nlohmann::json data2 = data1;
350};
351
352TEST_F(TestTriggerManagerStorage, triggerManagerCtorAddTriggerFromStorage)
353{
354 triggerFactoryMock.expectMake(TriggerParams(), _, Ref(storageMock));
Szymon Dompkee28aa532021-10-27 12:33:12 +0200355 triggerFactoryMock.expectMake(
356 TriggerParams().id("Trigger2").name("Second Trigger"), _,
357 Ref(storageMock));
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100358 EXPECT_CALL(storageMock, remove(_)).Times(0);
359
360 sut = makeTriggerManager();
361}
362
363TEST_F(TestTriggerManagerStorage,
364 triggerManagerCtorRemoveDiscreteTriggerFromStorage)
365{
366 LabeledTriggerThresholdParams thresholdParams =
367 std::vector<discrete::LabeledThresholdParam>{
Szymon Dompke9f346792021-07-14 21:07:11 +0200368 {"userId1", discrete::Severity::warning, 15, "10.0"},
369 {"userId2", discrete::Severity::critical, 5, "20.0"}};
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100370
371 data1["ThresholdParamsDiscriminator"] = thresholdParams.index();
372
373 data1["ThresholdParams"] =
374 utils::labeledThresholdParamsToJson(thresholdParams);
375
376 EXPECT_CALL(storageMock, remove(FilePath("trigger1"))).Times(0);
377
378 sut = makeTriggerManager();
379}
380
381TEST_F(TestTriggerManagerStorage,
382 triggerManagerCtorRemoveDiscreteTriggerFromStorage2)
383{
384 data1["IsDiscrete"] = true;
385
386 EXPECT_CALL(storageMock, remove(FilePath("trigger1"))).Times(0);
387
388 sut = makeTriggerManager();
389}
390
391TEST_F(TestTriggerManagerStorage,
392 triggerManagerCtorAddProperRemoveInvalidTriggerFromStorage)
393{
394 data1["Version"] = Trigger::triggerVersion - 1;
395
Szymon Dompkee28aa532021-10-27 12:33:12 +0200396 triggerFactoryMock.expectMake(
397 TriggerParams().id("Trigger2").name("Second Trigger"), _,
398 Ref(storageMock));
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100399 EXPECT_CALL(storageMock, remove(FilePath("trigger1")));
400
401 sut = makeTriggerManager();
402}