blob: ea4f0b978e08f7d009f51fd17b1cef82ff43d644 [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
126TEST_F(TestTriggerManager, addTriggerWithoutIdAndName)
127{
128 triggerFactoryMock
129 .expectMake(TriggerParams()
130 .id(TriggerManager::triggerNameDefault)
131 .name(TriggerManager::triggerNameDefault),
132 Ref(*sut), Ref(storageMock))
133 .WillOnce(Return(ByMove(std::move(triggerMockPtr))));
134
135 auto [ec, path] = addTrigger(TriggerParams().id("").name(""));
136 EXPECT_THAT(ec.value(), Eq(boost::system::errc::success));
137 EXPECT_THAT(path, Not(Eq("")));
138}
139
140TEST_F(TestTriggerManager, addTriggerWithPrefixId)
141{
142 triggerFactoryMock
143 .expectMake(TriggerParams()
144 .id("TelemetryService/HackyName")
145 .name("Hacky/Name!@#$"),
146 Ref(*sut), Ref(storageMock))
147 .WillOnce(Return(ByMove(std::move(triggerMockPtr))));
148
149 auto [ec, path] = addTrigger(
150 TriggerParams().id("TelemetryService/").name("Hacky/Name!@#$"));
151 EXPECT_THAT(ec.value(), Eq(boost::system::errc::success));
152 EXPECT_THAT(path, Not(Eq("")));
153}
154
155TEST_F(TestTriggerManager, addTriggerWithoutIdTwice)
156{
157 addTrigger(TriggerParams().id(""));
158
159 auto [ec, path] = addTrigger(TriggerParams().id(""));
160 EXPECT_THAT(ec.value(), Eq(boost::system::errc::success));
161 EXPECT_THAT(path, Not(Eq("")));
162}
163
164TEST_F(TestTriggerManager, addTriggerWithoutIdAndWithLongNameTwice)
165{
166 addTrigger(TriggerParams().id("").name(
167 std::string(2 * TriggerManager::maxTriggerIdLength, 'z')));
168
169 auto [ec, path] = addTrigger(TriggerParams().id("").name(
170 std::string(2 * TriggerManager::maxTriggerIdLength, 'z')));
171 EXPECT_THAT(ec.value(), Eq(boost::system::errc::success));
172 EXPECT_THAT(path, Not(Eq("")));
173}
174
175TEST_F(TestTriggerManager, addTriggerWithMaxLengthId)
176{
177 auto triggerId = std::string(TriggerManager::maxTriggerIdLength, 'z');
178 auto triggerParams = TriggerParams().id(triggerId);
179
180 triggerFactoryMock.expectMake(triggerParams, Ref(*sut), Ref(storageMock))
181 .WillOnce(Return(ByMove(std::move(triggerMockPtr))));
182
183 auto [ec, path] = addTrigger(triggerParams);
184
185 EXPECT_THAT(ec.value(), Eq(boost::system::errc::success));
186 EXPECT_THAT(path, Eq(triggerMock.getPath()));
187}
188
189TEST_F(TestTriggerManager, DISABLED_failToAddTriggerWithTooLongId)
190{
191 auto triggerId = std::string(TriggerManager::maxTriggerIdLength + 1, 'z');
192 auto triggerParams = TriggerParams().id(triggerId);
193
194 triggerFactoryMock.expectMake(std::nullopt, Ref(*sut), Ref(storageMock))
195 .Times(0);
196
197 auto [ec, path] = addTrigger(triggerParams);
198
199 EXPECT_THAT(ec.value(), Eq(boost::system::errc::invalid_argument));
200 EXPECT_THAT(path, Eq(std::string()));
201}
202
Wludzik, Jozef1477fe62021-01-02 11:56:10 +0100203TEST_F(TestTriggerManager, DISABLED_failToAddTriggerWhenMaxTriggerIsReached)
Wludzik, Jozef76833cb2020-12-21 14:42:41 +0100204{
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100205 auto triggerParams = TriggerParams();
206
Cezary Zwolaka4e67612021-02-18 13:16:16 +0100207 triggerFactoryMock.expectMake(std::nullopt, Ref(*sut), Ref(storageMock))
Wludzik, Jozef76833cb2020-12-21 14:42:41 +0100208 .Times(TriggerManager::maxTriggers);
209
210 for (size_t i = 0; i < TriggerManager::maxTriggers; i++)
211 {
Szymon Dompkee28aa532021-10-27 12:33:12 +0200212 triggerParams.id(TriggerParams().id() + std::to_string(i));
Wludzik, Jozef76833cb2020-12-21 14:42:41 +0100213
214 auto [ec, path] = addTrigger(triggerParams);
215 EXPECT_THAT(ec.value(), Eq(boost::system::errc::success));
216 }
217
Szymon Dompkee28aa532021-10-27 12:33:12 +0200218 triggerParams.id(TriggerParams().id() +
219 std::to_string(TriggerManager::maxTriggers));
Wludzik, Jozef76833cb2020-12-21 14:42:41 +0100220 auto [ec, path] = addTrigger(triggerParams);
221 EXPECT_THAT(ec.value(), Eq(boost::system::errc::too_many_files_open));
222 EXPECT_THAT(path, Eq(std::string()));
223}
224
225TEST_F(TestTriggerManager, removeTrigger)
226{
227 {
228 InSequence seq;
Cezary Zwolaka4e67612021-02-18 13:16:16 +0100229 triggerFactoryMock
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100230 .expectMake(TriggerParams(), Ref(*sut), Ref(storageMock))
Wludzik, Jozef76833cb2020-12-21 14:42:41 +0100231 .WillOnce(Return(ByMove(std::move(triggerMockPtr))));
232 EXPECT_CALL(triggerMock, Die());
233 EXPECT_CALL(checkPoint, Call("end"));
234 }
235
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100236 addTrigger(TriggerParams());
Wludzik, Jozef76833cb2020-12-21 14:42:41 +0100237 sut->removeTrigger(&triggerMock);
238 checkPoint.Call("end");
239}
240
241TEST_F(TestTriggerManager, removingTriggerThatIsNotInContainerHasNoEffect)
242{
243 {
244 InSequence seq;
245 EXPECT_CALL(checkPoint, Call("end"));
246 EXPECT_CALL(triggerMock, Die());
247 }
248
249 sut->removeTrigger(&triggerMock);
250 checkPoint.Call("end");
251}
252
253TEST_F(TestTriggerManager, removingSameTriggerTwiceHasNoSideEffect)
254{
255 {
256 InSequence seq;
Cezary Zwolaka4e67612021-02-18 13:16:16 +0100257 triggerFactoryMock
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100258 .expectMake(TriggerParams(), Ref(*sut), Ref(storageMock))
Wludzik, Jozef76833cb2020-12-21 14:42:41 +0100259 .WillOnce(Return(ByMove(std::move(triggerMockPtr))));
260 EXPECT_CALL(triggerMock, Die());
261 EXPECT_CALL(checkPoint, Call("end"));
262 }
263
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100264 addTrigger(TriggerParams());
Wludzik, Jozef76833cb2020-12-21 14:42:41 +0100265 sut->removeTrigger(&triggerMock);
266 sut->removeTrigger(&triggerMock);
267 checkPoint.Call("end");
268}
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100269
270class TestTriggerManagerStorage : public TestTriggerManager
271{
272 public:
273 using FilePath = interfaces::JsonStorage::FilePath;
274 using DirectoryPath = interfaces::JsonStorage::DirectoryPath;
275
276 void SetUp() override
277 {
278 ON_CALL(storageMock, list())
279 .WillByDefault(Return(std::vector<FilePath>{
280 {FilePath("trigger1")}, {FilePath("trigger2")}}));
281
282 ON_CALL(storageMock, load(FilePath("trigger1")))
283 .WillByDefault(InvokeWithoutArgs([this] { return data1; }));
284
Szymon Dompkee28aa532021-10-27 12:33:12 +0200285 data2["Id"] = "Trigger2";
286 data2["Name"] = "Second Trigger";
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100287 ON_CALL(storageMock, load(FilePath("trigger2")))
288 .WillByDefault(InvokeWithoutArgs([this] { return data2; }));
289 }
290
291 nlohmann::json data1 = nlohmann::json{
292 {"Version", Trigger::triggerVersion},
Szymon Dompkee28aa532021-10-27 12:33:12 +0200293 {"Id", TriggerParams().id()},
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100294 {"Name", TriggerParams().name()},
295 {"ThresholdParamsDiscriminator",
296 TriggerParams().thresholdParams().index()},
Szymon Dompke94f71c52021-12-10 07:16:33 +0100297 {"TriggerActions", utils::transform(TriggerParams().triggerActions(),
298 [](const auto& action) {
299 return actionToString(action);
300 })},
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100301 {"ThresholdParams", utils::labeledThresholdParamsToJson(
302 TriggerParams().thresholdParams())},
Krzysztof Grobelnyb8cc78d2021-11-29 15:54:53 +0100303 {"ReportIds", TriggerParams().reportIds()},
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100304 {"Sensors", TriggerParams().sensors()}};
305
306 nlohmann::json data2 = data1;
307};
308
309TEST_F(TestTriggerManagerStorage, triggerManagerCtorAddTriggerFromStorage)
310{
311 triggerFactoryMock.expectMake(TriggerParams(), _, Ref(storageMock));
Szymon Dompkee28aa532021-10-27 12:33:12 +0200312 triggerFactoryMock.expectMake(
313 TriggerParams().id("Trigger2").name("Second Trigger"), _,
314 Ref(storageMock));
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100315 EXPECT_CALL(storageMock, remove(_)).Times(0);
316
317 sut = makeTriggerManager();
318}
319
320TEST_F(TestTriggerManagerStorage,
321 triggerManagerCtorRemoveDiscreteTriggerFromStorage)
322{
323 LabeledTriggerThresholdParams thresholdParams =
324 std::vector<discrete::LabeledThresholdParam>{
Szymon Dompke9f346792021-07-14 21:07:11 +0200325 {"userId1", discrete::Severity::warning, 15, "10.0"},
326 {"userId2", discrete::Severity::critical, 5, "20.0"}};
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100327
328 data1["ThresholdParamsDiscriminator"] = thresholdParams.index();
329
330 data1["ThresholdParams"] =
331 utils::labeledThresholdParamsToJson(thresholdParams);
332
333 EXPECT_CALL(storageMock, remove(FilePath("trigger1"))).Times(0);
334
335 sut = makeTriggerManager();
336}
337
338TEST_F(TestTriggerManagerStorage,
339 triggerManagerCtorRemoveDiscreteTriggerFromStorage2)
340{
341 data1["IsDiscrete"] = true;
342
343 EXPECT_CALL(storageMock, remove(FilePath("trigger1"))).Times(0);
344
345 sut = makeTriggerManager();
346}
347
348TEST_F(TestTriggerManagerStorage,
349 triggerManagerCtorAddProperRemoveInvalidTriggerFromStorage)
350{
351 data1["Version"] = Trigger::triggerVersion - 1;
352
Szymon Dompkee28aa532021-10-27 12:33:12 +0200353 triggerFactoryMock.expectMake(
354 TriggerParams().id("Trigger2").name("Second Trigger"), _,
355 Ref(storageMock));
Cezary Zwolak4416fce2021-03-17 03:21:06 +0100356 EXPECT_CALL(storageMock, remove(FilePath("trigger1")));
357
358 sut = makeTriggerManager();
359}