blob: efdac652f4f4921b150acf060272a9656b916491 [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;
13
14class TestTriggerManager : public Test
15{
16 public:
17 std::pair<boost::system::error_code, std::string>
18 addTrigger(const TriggerParams& params)
19 {
Cezary Zwolak4416fce2021-03-17 03:21:06 +010020 const auto sensorInfos =
21 utils::fromLabeledSensorsInfo(params.sensors());
22
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010023 std::promise<std::pair<boost::system::error_code, std::string>>
24 addTriggerPromise;
25 DbusEnvironment::getBus()->async_method_call(
26 [&addTriggerPromise](boost::system::error_code ec,
27 const std::string& path) {
28 addTriggerPromise.set_value({ec, path});
29 },
30 DbusEnvironment::serviceName(), TriggerManager::triggerManagerPath,
Szymon Dompkee28aa532021-10-27 12:33:12 +020031 TriggerManager::triggerManagerIfaceName, "AddTrigger", params.id(),
Szymon Dompke94f71c52021-12-10 07:16:33 +010032 params.name(),
33 utils::transform(
34 params.triggerActions(),
35 [](const auto& action) { return actionToString(action); }),
36 sensorInfos, params.reportIds(),
Cezary Zwolak4416fce2021-03-17 03:21:06 +010037 std::visit(utils::FromLabeledThresholdParamConversion(),
38 params.thresholdParams()));
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010039 return DbusEnvironment::waitForFuture(addTriggerPromise.get_future());
40 }
41
Cezary Zwolak4416fce2021-03-17 03:21:06 +010042 std::unique_ptr<TriggerManager> makeTriggerManager()
43 {
44 return std::make_unique<TriggerManager>(
45 std::move(triggerFactoryMockPtr), std::move(storageMockPtr),
46 DbusEnvironment::getObjServer());
47 }
48
49 void SetUp() override
50 {
51 sut = makeTriggerManager();
52 }
53
Cezary Zwolaka4e67612021-02-18 13:16:16 +010054 std::unique_ptr<StorageMock> storageMockPtr =
55 std::make_unique<NiceMock<StorageMock>>();
56 StorageMock& storageMock = *storageMockPtr;
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010057 std::unique_ptr<TriggerFactoryMock> triggerFactoryMockPtr =
58 std::make_unique<NiceMock<TriggerFactoryMock>>();
59 TriggerFactoryMock& triggerFactoryMock = *triggerFactoryMockPtr;
60 std::unique_ptr<TriggerMock> triggerMockPtr =
Szymon Dompkee28aa532021-10-27 12:33:12 +020061 std::make_unique<NiceMock<TriggerMock>>(TriggerParams().id());
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010062 TriggerMock& triggerMock = *triggerMockPtr;
Cezary Zwolak4416fce2021-03-17 03:21:06 +010063 std::unique_ptr<TriggerManager> sut;
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010064 MockFunction<void(std::string)> checkPoint;
65};
66
67TEST_F(TestTriggerManager, addTrigger)
68{
Cezary Zwolak4416fce2021-03-17 03:21:06 +010069 triggerFactoryMock.expectMake(TriggerParams(), Ref(*sut), Ref(storageMock))
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010070 .WillOnce(Return(ByMove(std::move(triggerMockPtr))));
71
Cezary Zwolak4416fce2021-03-17 03:21:06 +010072 auto [ec, path] = addTrigger(TriggerParams());
Wludzik, Jozef76833cb2020-12-21 14:42:41 +010073 EXPECT_THAT(ec.value(), Eq(boost::system::errc::success));
74 EXPECT_THAT(path, Eq(triggerMock.getPath()));
75}
76
Szymon Dompkef763c9e2021-03-12 09:19:22 +010077TEST_F(TestTriggerManager, addTriggerWithDiscreteThresholds)
78{
79 TriggerParams triggerParamsDiscrete;
Cezary Zwolak4416fce2021-03-17 03:21:06 +010080 auto thresholds = std::vector<discrete::LabeledThresholdParam>{
Szymon Dompke9f346792021-07-14 21:07:11 +020081 {"discrete_threshold1", discrete::Severity::ok, 10, "11.0"},
82 {"discrete_threshold2", discrete::Severity::warning, 10, "12.0"},
83 {"discrete_threshold3", discrete::Severity::critical, 10, "13.0"}};
Szymon Dompkef763c9e2021-03-12 09:19:22 +010084
Szymon Dompke20013012021-07-23 09:54:20 +020085 triggerParamsDiscrete.thresholdParams(thresholds);
Szymon Dompkef763c9e2021-03-12 09:19:22 +010086
87 auto [ec, path] = addTrigger(triggerParamsDiscrete);
88 EXPECT_THAT(ec.value(), Eq(boost::system::errc::success));
89 EXPECT_THAT(path, Eq(triggerMock.getPath()));
90}
91
92TEST_F(TestTriggerManager, addDiscreteTriggerWithoutThresholds)
93{
94 TriggerParams triggerParamsDiscrete;
Cezary Zwolak4416fce2021-03-17 03:21:06 +010095 auto thresholds = std::vector<discrete::LabeledThresholdParam>();
Szymon Dompkef763c9e2021-03-12 09:19:22 +010096
Szymon Dompke20013012021-07-23 09:54:20 +020097 triggerParamsDiscrete.thresholdParams(thresholds);
Szymon Dompkef763c9e2021-03-12 09:19:22 +010098
99 auto [ec, path] = addTrigger(triggerParamsDiscrete);
100 EXPECT_THAT(ec.value(), Eq(boost::system::errc::success));
101 EXPECT_THAT(path, Eq(triggerMock.getPath()));
102}
103
Wludzik, Jozef1477fe62021-01-02 11:56:10 +0100104TEST_F(TestTriggerManager, DISABLED_failToAddTriggerTwice)
Wludzik, Jozef76833cb2020-12-21 14:42:41 +0100105{
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100106 triggerFactoryMock.expectMake(TriggerParams(), Ref(*sut), Ref(storageMock))
Wludzik, Jozef76833cb2020-12-21 14:42:41 +0100107 .WillOnce(Return(ByMove(std::move(triggerMockPtr))));
108
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100109 addTrigger(TriggerParams());
Wludzik, Jozef76833cb2020-12-21 14:42:41 +0100110
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100111 auto [ec, path] = addTrigger(TriggerParams());
Wludzik, Jozef76833cb2020-12-21 14:42:41 +0100112 EXPECT_THAT(ec.value(), Eq(boost::system::errc::file_exists));
113 EXPECT_THAT(path, Eq(std::string()));
114}
115
Szymon Dompkee28aa532021-10-27 12:33:12 +0200116TEST_F(TestTriggerManager, DISABLED_failToAddTriggerWithInvalidId)
117{
118 triggerFactoryMock.expectMake(std::nullopt, Ref(*sut), Ref(storageMock))
119 .Times(0);
120
121 auto [ec, path] = addTrigger(TriggerParams().id("not valid?"));
122 EXPECT_THAT(ec.value(), Eq(boost::system::errc::invalid_argument));
123 EXPECT_THAT(path, Eq(std::string()));
124}
125
Szymon Dompkeb4ef22e2022-02-07 15:15:12 +0100126TEST_F(TestTriggerManager, DISABLED_failToAddTriggerWithDuplicatesInReportsIds)
127{
128 triggerFactoryMock.expectMake(std::nullopt, Ref(*sut), Ref(storageMock))
129 .Times(0);
130
131 auto [ec, path] = addTrigger(
132 TriggerParams().reportIds({"trigger1", "trigger2", "trigger1"}));
133 EXPECT_THAT(ec.value(), Eq(boost::system::errc::invalid_argument));
134 EXPECT_THAT(path, Eq(std::string()));
135}
136
Szymon Dompkee28aa532021-10-27 12:33:12 +0200137TEST_F(TestTriggerManager, addTriggerWithoutIdAndName)
138{
139 triggerFactoryMock
140 .expectMake(TriggerParams()
141 .id(TriggerManager::triggerNameDefault)
142 .name(TriggerManager::triggerNameDefault),
143 Ref(*sut), Ref(storageMock))
144 .WillOnce(Return(ByMove(std::move(triggerMockPtr))));
145
146 auto [ec, path] = addTrigger(TriggerParams().id("").name(""));
147 EXPECT_THAT(ec.value(), Eq(boost::system::errc::success));
148 EXPECT_THAT(path, Not(Eq("")));
149}
150
151TEST_F(TestTriggerManager, addTriggerWithPrefixId)
152{
153 triggerFactoryMock
154 .expectMake(TriggerParams()
155 .id("TelemetryService/HackyName")
156 .name("Hacky/Name!@#$"),
157 Ref(*sut), Ref(storageMock))
158 .WillOnce(Return(ByMove(std::move(triggerMockPtr))));
159
160 auto [ec, path] = addTrigger(
161 TriggerParams().id("TelemetryService/").name("Hacky/Name!@#$"));
162 EXPECT_THAT(ec.value(), Eq(boost::system::errc::success));
163 EXPECT_THAT(path, Not(Eq("")));
164}
165
166TEST_F(TestTriggerManager, addTriggerWithoutIdTwice)
167{
168 addTrigger(TriggerParams().id(""));
169
170 auto [ec, path] = addTrigger(TriggerParams().id(""));
171 EXPECT_THAT(ec.value(), Eq(boost::system::errc::success));
172 EXPECT_THAT(path, Not(Eq("")));
173}
174
175TEST_F(TestTriggerManager, addTriggerWithoutIdAndWithLongNameTwice)
176{
177 addTrigger(TriggerParams().id("").name(
178 std::string(2 * TriggerManager::maxTriggerIdLength, 'z')));
179
180 auto [ec, path] = addTrigger(TriggerParams().id("").name(
181 std::string(2 * TriggerManager::maxTriggerIdLength, 'z')));
182 EXPECT_THAT(ec.value(), Eq(boost::system::errc::success));
183 EXPECT_THAT(path, Not(Eq("")));
184}
185
186TEST_F(TestTriggerManager, addTriggerWithMaxLengthId)
187{
188 auto triggerId = std::string(TriggerManager::maxTriggerIdLength, 'z');
189 auto triggerParams = TriggerParams().id(triggerId);
190
191 triggerFactoryMock.expectMake(triggerParams, Ref(*sut), Ref(storageMock))
192 .WillOnce(Return(ByMove(std::move(triggerMockPtr))));
193
194 auto [ec, path] = addTrigger(triggerParams);
195
196 EXPECT_THAT(ec.value(), Eq(boost::system::errc::success));
197 EXPECT_THAT(path, Eq(triggerMock.getPath()));
198}
199
200TEST_F(TestTriggerManager, DISABLED_failToAddTriggerWithTooLongId)
201{
202 auto triggerId = std::string(TriggerManager::maxTriggerIdLength + 1, 'z');
203 auto triggerParams = TriggerParams().id(triggerId);
204
205 triggerFactoryMock.expectMake(std::nullopt, Ref(*sut), Ref(storageMock))
206 .Times(0);
207
208 auto [ec, path] = addTrigger(triggerParams);
209
210 EXPECT_THAT(ec.value(), Eq(boost::system::errc::invalid_argument));
211 EXPECT_THAT(path, Eq(std::string()));
212}
213
Wludzik, Jozef1477fe62021-01-02 11:56:10 +0100214TEST_F(TestTriggerManager, DISABLED_failToAddTriggerWhenMaxTriggerIsReached)
Wludzik, Jozef76833cb2020-12-21 14:42:41 +0100215{
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100216 auto triggerParams = TriggerParams();
217
Cezary Zwolaka4e67612021-02-18 13:16:16 +0100218 triggerFactoryMock.expectMake(std::nullopt, Ref(*sut), Ref(storageMock))
Wludzik, Jozef76833cb2020-12-21 14:42:41 +0100219 .Times(TriggerManager::maxTriggers);
220
221 for (size_t i = 0; i < TriggerManager::maxTriggers; i++)
222 {
Szymon Dompkee28aa532021-10-27 12:33:12 +0200223 triggerParams.id(TriggerParams().id() + std::to_string(i));
Wludzik, Jozef76833cb2020-12-21 14:42:41 +0100224
225 auto [ec, path] = addTrigger(triggerParams);
226 EXPECT_THAT(ec.value(), Eq(boost::system::errc::success));
227 }
228
Szymon Dompkee28aa532021-10-27 12:33:12 +0200229 triggerParams.id(TriggerParams().id() +
230 std::to_string(TriggerManager::maxTriggers));
Wludzik, Jozef76833cb2020-12-21 14:42:41 +0100231 auto [ec, path] = addTrigger(triggerParams);
232 EXPECT_THAT(ec.value(), Eq(boost::system::errc::too_many_files_open));
233 EXPECT_THAT(path, Eq(std::string()));
234}
235
236TEST_F(TestTriggerManager, removeTrigger)
237{
238 {
239 InSequence seq;
Cezary Zwolaka4e67612021-02-18 13:16:16 +0100240 triggerFactoryMock
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100241 .expectMake(TriggerParams(), Ref(*sut), Ref(storageMock))
Wludzik, Jozef76833cb2020-12-21 14:42:41 +0100242 .WillOnce(Return(ByMove(std::move(triggerMockPtr))));
243 EXPECT_CALL(triggerMock, Die());
244 EXPECT_CALL(checkPoint, Call("end"));
245 }
246
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100247 addTrigger(TriggerParams());
Wludzik, Jozef76833cb2020-12-21 14:42:41 +0100248 sut->removeTrigger(&triggerMock);
249 checkPoint.Call("end");
250}
251
252TEST_F(TestTriggerManager, removingTriggerThatIsNotInContainerHasNoEffect)
253{
254 {
255 InSequence seq;
256 EXPECT_CALL(checkPoint, Call("end"));
257 EXPECT_CALL(triggerMock, Die());
258 }
259
260 sut->removeTrigger(&triggerMock);
261 checkPoint.Call("end");
262}
263
264TEST_F(TestTriggerManager, removingSameTriggerTwiceHasNoSideEffect)
265{
266 {
267 InSequence seq;
Cezary Zwolaka4e67612021-02-18 13:16:16 +0100268 triggerFactoryMock
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100269 .expectMake(TriggerParams(), Ref(*sut), Ref(storageMock))
Wludzik, Jozef76833cb2020-12-21 14:42:41 +0100270 .WillOnce(Return(ByMove(std::move(triggerMockPtr))));
271 EXPECT_CALL(triggerMock, Die());
272 EXPECT_CALL(checkPoint, Call("end"));
273 }
274
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100275 addTrigger(TriggerParams());
Wludzik, Jozef76833cb2020-12-21 14:42:41 +0100276 sut->removeTrigger(&triggerMock);
277 sut->removeTrigger(&triggerMock);
278 checkPoint.Call("end");
279}
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100280class TestTriggerManagerStorage : public TestTriggerManager
281{
282 public:
283 using FilePath = interfaces::JsonStorage::FilePath;
284 using DirectoryPath = interfaces::JsonStorage::DirectoryPath;
285
286 void SetUp() override
287 {
288 ON_CALL(storageMock, list())
289 .WillByDefault(Return(std::vector<FilePath>{
290 {FilePath("trigger1")}, {FilePath("trigger2")}}));
291
292 ON_CALL(storageMock, load(FilePath("trigger1")))
293 .WillByDefault(InvokeWithoutArgs([this] { return data1; }));
294
Szymon Dompkee28aa532021-10-27 12:33:12 +0200295 data2["Id"] = "Trigger2";
296 data2["Name"] = "Second Trigger";
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100297 ON_CALL(storageMock, load(FilePath("trigger2")))
298 .WillByDefault(InvokeWithoutArgs([this] { return data2; }));
299 }
300
301 nlohmann::json data1 = nlohmann::json{
302 {"Version", Trigger::triggerVersion},
Szymon Dompkee28aa532021-10-27 12:33:12 +0200303 {"Id", TriggerParams().id()},
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100304 {"Name", TriggerParams().name()},
305 {"ThresholdParamsDiscriminator",
306 TriggerParams().thresholdParams().index()},
Szymon Dompke94f71c52021-12-10 07:16:33 +0100307 {"TriggerActions", utils::transform(TriggerParams().triggerActions(),
308 [](const auto& action) {
309 return actionToString(action);
310 })},
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100311 {"ThresholdParams", utils::labeledThresholdParamsToJson(
312 TriggerParams().thresholdParams())},
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +0100313 {"ReportIds", TriggerParams().reportIds()},
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100314 {"Sensors", TriggerParams().sensors()}};
315
316 nlohmann::json data2 = data1;
317};
318
319TEST_F(TestTriggerManagerStorage, triggerManagerCtorAddTriggerFromStorage)
320{
321 triggerFactoryMock.expectMake(TriggerParams(), _, Ref(storageMock));
Szymon Dompkee28aa532021-10-27 12:33:12 +0200322 triggerFactoryMock.expectMake(
323 TriggerParams().id("Trigger2").name("Second Trigger"), _,
324 Ref(storageMock));
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100325 EXPECT_CALL(storageMock, remove(_)).Times(0);
326
327 sut = makeTriggerManager();
328}
329
330TEST_F(TestTriggerManagerStorage,
331 triggerManagerCtorRemoveDiscreteTriggerFromStorage)
332{
333 LabeledTriggerThresholdParams thresholdParams =
334 std::vector<discrete::LabeledThresholdParam>{
Szymon Dompke9f346792021-07-14 21:07:11 +0200335 {"userId1", discrete::Severity::warning, 15, "10.0"},
336 {"userId2", discrete::Severity::critical, 5, "20.0"}};
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100337
338 data1["ThresholdParamsDiscriminator"] = thresholdParams.index();
339
340 data1["ThresholdParams"] =
341 utils::labeledThresholdParamsToJson(thresholdParams);
342
343 EXPECT_CALL(storageMock, remove(FilePath("trigger1"))).Times(0);
344
345 sut = makeTriggerManager();
346}
347
348TEST_F(TestTriggerManagerStorage,
349 triggerManagerCtorRemoveDiscreteTriggerFromStorage2)
350{
351 data1["IsDiscrete"] = true;
352
353 EXPECT_CALL(storageMock, remove(FilePath("trigger1"))).Times(0);
354
355 sut = makeTriggerManager();
356}
357
358TEST_F(TestTriggerManagerStorage,
359 triggerManagerCtorAddProperRemoveInvalidTriggerFromStorage)
360{
361 data1["Version"] = Trigger::triggerVersion - 1;
362
Szymon Dompkee28aa532021-10-27 12:33:12 +0200363 triggerFactoryMock.expectMake(
364 TriggerParams().id("Trigger2").name("Second Trigger"), _,
365 Ref(storageMock));
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100366 EXPECT_CALL(storageMock, remove(FilePath("trigger1")));
367
368 sut = makeTriggerManager();
369}